/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : Installer.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */
package ciss.phase_viewer.install;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;

import javax.swing.JFrame;

import ciss.phase_viewer.common.MyMessageBox;
import ciss.phase_viewer.common.Utils;

public class Installer {

    private String FS = System.getProperty("file.separator");
    private String LS = System.getProperty("line.separator");
    private String PS = System.getProperty("path.separator");
    private String whiteSpace = " ";

    private String chaseRoot = (new File(System.getProperty("user.dir")))
            .getParent();
    private String chaseInstDir = chaseRoot + FS + "install" + FS
            + "install_files";
    private String binDir = chaseRoot + FS + "bin";
    private String libDir = chaseRoot + FS + "lib";
    private String progDir = chaseRoot + FS + "programs";

    private String acvOrig = chaseInstDir + FS + "acvconfig";
    private String chaseiniOrig = chaseInstDir + FS + "phase-viewer.ini";
    private String elementinfoOrig = chaseInstDir + FS + "elementinfo";
    private String sizeinfoOrig = chaseInstDir + FS + "sizeinfo";

    private String homeDir = System.getProperty("user.home");
    private String chaseDir = homeDir + FS + ".phase-viewer";
    private String templateDir = chaseDir + FS + "templates";
    private String kpointsDir = templateDir + FS + "kpoints";
    private String inputDir = templateDir + FS + "inputfiles";
    private String ppDir = templateDir + FS + "pp";

    private String templateDirOrig = chaseInstDir + FS + "templates";
    private String kpointsDirOrig = templateDirOrig + FS + "kpoints";
    private String inputDirOrig = templateDirOrig + FS + "inputfiles";
    private String ppDirOrig = templateDirOrig + FS + "pp";

    private String[] args;
    private String mode = "reinstall";

    private String scriptPath;
    private String rc;
    private Vector optVect = new Vector();

    private InstallerPanel panel;

    /**
     * 
     * @uml.property name="mbox"
     * @uml.associationEnd multiplicity="(0 1)"
     */
    private MyMessageBox mbox = new MyMessageBox();

    private boolean win = false;
    private String javapath;

    /* for use with the progress bar */
    private int numTasks = 0;
    private int currentTask = 0;
    private String message = new String();

    /**
     * 
     * @uml.property name="progressbar"
     * @uml.associationEnd multiplicity="(0 1)"
     */
    private ProgressBar progressbar;

    private JFrame frame;

    private Properties prop;

    private boolean guiEnabled = false;

    public void Installer() {
    }

    protected void initiateProgressBar() {
        // 'progressbar' does not seem to work for me... pending
        /*
         * frame = new JFrame("installing chase-3pt ... ");
         * frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         * 
         * progressbar = new ProgressBar(this); progressbar.go(); Container co =
         * frame.getContentPane(); co.add(progressbar);
         * 
         * frame.setSize(400,300); frame.pack(); frame.setVisible(true);
         */
    }

    /** boot installer gui */
    protected void bootGUI() {
        panel = new InstallerPanel(this);
    }

    protected void bootGUI(boolean guiEnabled) {
        this.guiEnabled = guiEnabled;
        panel = new InstallerPanel(this, guiEnabled);
    }

    /**
     * set arguments
     * 
     * @uml.property name="args"
     */
    protected void setArgs(String[] args) {
        this.args = args;
    }

    /** parse arguments @deprecated */
    protected void parseArgs() {
        String argsi;
        String value;
        for (int i = 0; i < args.length; i++) {
            StringTokenizer st = new StringTokenizer(args[i], "=");
            if (st.countTokens() == 2) {
                argsi = st.nextToken().trim();
                value = st.nextToken().trim();
                if (argsi.equalsIgnoreCase("mode")
                        || argsi.equalsIgnoreCase("-mode")) {
                    mode = value;
                }
                if (argsi.equalsIgnoreCase("rc")
                        || argsi.equalsIgnoreCase("-rc")) {
                    rc = value;
                }
                if (argsi.equalsIgnoreCase("java_options")
                        || argsi.equalsIgnoreCase("-java_options")) {
                    StringTokenizer stj = new StringTokenizer(value, ",");
                    while (stj.hasMoreElements()) {
                        optVect.addElement(stj.nextToken());
                    }
                }

            }
        }
    }

    /** set options */
    protected void setRC(String rc) {
        this.rc = rc;
        this.checkRC();
    }

    /** set java path */
    protected void setJava(String javapath) {
        this.javapath = javapath;
    }

    /** set properties */
    protected void setProperties(Properties prop) {
        this.prop = prop;
    }

    /** set java options */
    protected void setJavaOpts(String value) {
        StringTokenizer stj = new StringTokenizer(value, ",");
        while (stj.hasMoreElements()) {
            optVect.addElement(stj.nextToken().trim());
        }
    }

    /**
     * get installation mode
     * 
     * @uml.property name="mode"
     */
    protected String getMode() {
        return this.mode;
    }

    /**
     * check if rc is present for chase, and further is executable
     */
    protected boolean checkRC() {
        boolean bret = true;

        scriptPath = new String();
        String scriptName = new String();
        String osName = System.getProperty("os.name");
        if (osName.toLowerCase().startsWith("windows")) {
            scriptName = "chase.bat";
            win = true;
        } else {
            scriptName = "chase";
        }

        if (rc != null) {
            scriptPath = rc + FS + scriptName;
        } else {
            scriptPath = binDir + FS + scriptName;
        }

        File file = new File(scriptPath);
        bret = file.exists();

        return bret;
    }

    /**
     * copy necessary directories/files
     * 
     * @return true if everything succeeded
     */
    protected boolean runInstaller() {

        System.out.println("*********** creating run command ***********");
        /* create rc, and copy it to the specified directory */

        String setPath = new String();
        if (System.getProperty("os.name").toLowerCase().trim()
                .startsWith("windows")) {
            progDir = prop.getProperty("gnuplotpath");
            setPath = "set path=" + prop.getProperty("chasedir") + FS
                    + prop.getProperty("gnuplotpath") + FS + PS
                    + prop.getProperty("chasedir") + FS
                    + prop.getProperty("perlpath") + FS + PS + "%path%" + LS;
        } else {
            setPath = "";
        }

        javapath = setPath + Utils.getPathDQ(javapath) + whiteSpace;
        for (int i = 0; i < optVect.size(); i++) {
            javapath += (String) optVect.get(i) + whiteSpace;
        }

        /* -D option */
        // libDir += System.getProperty("path.separator");
        // +System.getProperty("java.library.path");
        String optD = " -Djava.library.path=" + Utils.getPathDQ(libDir);
        javapath += optD;

        /* chase home */
        String chaseHome = " -Dpviewer.home=" + Utils.getPathDQ(chaseRoot);
        javapath += chaseHome;

        javapath += " -jar ";
        String binPath = Utils.getPathDQ((new File(binDir + FS
                + "phase-viewer.jar")).getAbsolutePath());
        javapath += binPath;

        try {
            FileWriter fwriter = new FileWriter(scriptPath);
            BufferedWriter bwriter = new BufferedWriter(fwriter);
            bwriter.write(javapath, 0, javapath.length());
            bwriter.flush();
            fwriter.close();
            System.out.println("created " + scriptPath);
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("failed to create run command");
            return false;
        }

        if (!win) {
            try {
                Process process = Runtime.getRuntime().exec(
                        "chmod 744 " + Utils.getPathDQ(scriptPath));
                System.out.println("changed permission of: "
                        + Utils.getPathDQ(scriptPath));
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("failed to change permission");
            }
        }
        System.out
                .println("*********** saving template phase-viewer.ini ***********");
        try {
            prop.store(new FileOutputStream(chaseiniOrig), "last modification:");
        } catch (Exception e) {
            e.printStackTrace();
            mbox.setText("failed to modify " + chaseiniOrig, !guiEnabled);
            System.exit(0);
        }

        return true;
    }

    /**
     * return number of tasks
     * 
     * @uml.property name="numTasks"
     */
    protected int getNumTasks() {
        return numTasks;
    }

    /** get status of current task */
    protected int getCurrent() {
        return currentTask;
    }

    /**
     * get message
     * 
     * @uml.property name="message"
     */
    protected String getMessage() {
        return message;
    }

    protected boolean isDone() {
        return (currentTask == numTasks);
    }

    /** start installation */
    protected void startInstall() {
        if (!(this.runInstaller())) {
            mbox.setText("failed installation ... check permission.",
                    !guiEnabled);
            System.exit(0);
        } else {
            System.out.println("installation finished");
            mbox.setText("finished installation of chase-3pt", !guiEnabled);
            System.exit(0);
        }
    }

    public static void main(String args[]) {
        java.util.Locale.setDefault(new java.util.Locale("en", "US"));

        Installer installer = new Installer();
        if (args.length == 0) {
            installer.bootGUI();
        } else {
            if (args[0].trim().equalsIgnoreCase("-with_gui")) {
                installer.bootGUI(true);
            } else {
                installer.bootGUI();
            }
        }
    }

}
