import java.util.Properties;
import java.util.Vector;
import java.util.StringTokenizer;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.io.*;
import javax.swing.*;
import javax.swing.JOptionPane;


public class WelcomeView extends WelcomeFrame {
    private static final String CLASSNAME   = "WelcomeView:: ";
  //  private static final String PROPS_DIR   = "config/";
   // private static final String PROPS_FILE  = "patch.properties";
  //  private static Properties props;
	private static ResourceBundle myResources;
    
    private String patchID;                     // patch ID from properties
    private String[] fileNames;
    private String sunmcDir;                    // SunMC3.0 location from Windows registry
    private String sourceDir;                   // patch SunMC3.0 directory
    private String destDir;
    private String args             = "/K";   // command line arguments for 'xcopy'
	private boolean patchName         = false;
 
    public WelcomeView() {
        InstallProgressBar.setVisible(false);
        loadPatchProps();
		getPatchID();
		if(patchName){
		 InstallButton.setName("uninstall");
		 InstallButton.setText(myResources.getString("uninstallButton"));
		 JTextArea1.setText(myResources.getString("uninstallMessage"));
		 }
		 else
		 {
		    InstallButton.setName("Install");
            InstallButton.setText(myResources.getString("installButton"));
			JTextArea1.setText(myResources.getString("installMessage"));
         }
		 setExitMessage(myResources.getString("exitMessage"));
    }
    



    /**
    * Method that implements the following:
    * 1. Check patch source files agants 'patch.properties' file;
    * 2. Renames the old files into 'filename.bak';
    * 3. Copies the new files.
    */
	void InstallButton_actionPerformed(java.awt.event.ActionEvent event) {
        InstallProgressBar.setVisible(true);
        checkSourceDir();
        getSunmcDir();
		JButton one = (JButton) event.getSource();
       if(one.getName().equals("Install"))
	   {
        final SwingWorker worker = new SwingWorker() {
            public Object construct() {
                boolean result = false;
		        if(backupOldFiles()) {
		            if(deleteOldFiles()) {
		                result = copyNewFiles();
		                if(result) {
		                    InstallButton.setEnabled(false);
							setPatchID();
		                }
		            }
		        }
                return new Boolean(result); // not used yet
            }
        };
        worker.start();  // required for SwingWorker 3
		
		}
		else
		{
           final SwingWorker worker = new SwingWorker() {
            public Object construct() {
                boolean result = false;
                 if(deleteOldFiles()) {
                    result = copyBackupFiles();
					if(result){
					  InstallButton.setEnabled(false);
					  deletePatchID();
					   }
					}
               return new Boolean(result);
             }
		  };
		  worker.start();
       }
	}
	
    /**
    * Loads 'patch.properties' file
    */
	void loadPatchProps() {
        // Load the properties file
   //     props = new Properties();
     //   props.put("planbase", PROPS_DIR);
       	try{
		       myResources = ResourceBundle.getBundle("config.patch", java.util.Locale.getDefault());
      //      FileInputStream in = new FileInputStream(props.getString("planbase") + PROPS_FILE);
       //     myResources.load(in);
       //     in.close();
        }
        catch (MissingResourceException e){
        //    System.out.println(CLASSNAME + " error while trying to access " + myResources_FILE);
          //  System.out.println(CLASSNAME + e.getMessage());
		  e.printStackTrace();
            System.exit(-1);
        }
        
        // convert filename list to array
        fileNames = listToArray(myResources.getString("filenames"));
        
	}

    /**
    * Checks if source directory (SunMC3.0) contains the patch files
    */
	void checkSourceDir() {
        for(int i=0; i<fileNames.length; i++) {
            File sourceFile = new File("." + File.separator + 
                myResources.getString("sourceDir") + File.separator + fileNames[i]);
            
            if(!sourceFile.exists()) {
		        JOptionPane.showMessageDialog(
		            this,
		            myResources.getString("sourceNotFound") + sourceFile.toString(), 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return;
		    }
		    
		    sourceDir = "." + File.separator + myResources.getString("sourceDir");
        }
	}
	
    /**
    * Queries executable to get SunMC3.0 location
    */
	void getSunmcDir() {
	    String queryCommand = 
	        myResources.getString("exeFile") + " " + myResources.getString("queryCommand") + " Path";
	    String output[] = runCommand(queryCommand, true);
	    
	    if(output.length > 0 && (output[0] != null && !output[0].trim().equals(""))) {
	        sunmcDir = output[0];
	        //System.out.println("sunmcDir = " + sunmcDir); //temp
	    }
	    else {
		    JOptionPane.showMessageDialog(
		        this,
		        myResources.getString("locationNotFound"), 
		        "Error", 
		        JOptionPane.ERROR_MESSAGE );
	    }
	}
	
void setPatchID() {
	    String queryCommand = 
	        myResources.getString("exeFile") + " " + myResources.getString("addEntryCommand") + " " + myResources.getString("patchName") + " " + myResources.getString("patchID");
			//System.out.println("add " + queryCommand);
	       String output[] = runCommand(queryCommand, true);
		   //System.out.println("value " + output[0]);
	}


void deletePatchID() {
     
       int num = ((Integer.parseInt(myResources.getString("patchID"))) -1);
       if( num > 0)
	   {
	        String queryCommand =
	        myResources.getString("exeFile") + " " + myResources.getString("addEntryCommand") + " " + myResources.getString("patchName") + " " + num; 
			String output[] = runCommand(queryCommand, true);
		    
       }
       else {

	       String queryCommand = 
	       myResources.getString("exeFile") + " " + myResources.getString("removeEntryCommand") + " " + myResources.getString("patchName");
	       String output[] = runCommand(queryCommand, true);
		  // System.out.println("value " + output[0]);
		  }
	}

 /**
    * Queries executable to get SunMC3.0 location
    */
	void getPatchID(){
	    String queryCommand = 
	        myResources.getString("exeFile") + " " + myResources.getString("queryCommand") + " " + myResources.getString("patchName");
	        String output[] = runCommand(queryCommand, true);
	    
	    if(output.length > 0 && (output[0] != null && !output[0].trim().equals(""))) {
		    int val         = Integer.parseInt(output[0]);
			int patch_id    = Integer.parseInt(myResources.getString("patchID"));
			String  message = myResources.getString("exitMess") + " " + myResources.getString("patchName") + "-" + val + "\n" + myResources.getString("reasonMess");
			if(val > patch_id){
           try {
	    	    // Beep
	    	   // Toolkit.getDefaultToolkit().beep();
	    	    // Show a confirmation dialog
	    	   int reply = JOptionPane.showConfirmDialog(this, 
	    	                                            message, 
	    	                                          "Exit?" , 
	    	                                          JOptionPane.DEFAULT_OPTION, 
	    	                                          JOptionPane.QUESTION_MESSAGE);
			   // If the confirmation was affirmative, handle exiting.
			
		    	this.setVisible(false);    // hide the Frame
		    	this.dispose();            // free the system resources
		    	System.exit(0);            // close the application
		        }catch (Exception e) {
                e.printStackTrace();
		        }
              }
			  else if(val == patch_id){
	           patchName = true;
              } 
         } 
	      //  System.out.println("sunmcDir = " + sunmcDir); //temp
	    }
	    




	public void doBackupOldFiles() {
        final SwingWorker worker = new SwingWorker() {
            public Object construct() {
                boolean result = backupOldFiles();
                return new Boolean(result); // not used yet
            }
        };
        worker.start();  // required for SwingWorker 3
	}
	    
	public void doDeleteOldFiles() {
        final SwingWorker worker = new SwingWorker() {
            public Object construct() {
                boolean result = deleteOldFiles();
                return new Boolean(result); // not used yet
            }
        };
        worker.start();
	}
    
    public void doCopyNewFiles() {
        final SwingWorker worker = new SwingWorker() {
            public Object construct() {
                boolean result = copyNewFiles();
                return new Boolean(result); // not used yet
            }
        };
        worker.start();
    }
	
	public boolean backupOldFiles() {
        for(int i=0; i<fileNames.length; i++) {
            String origString = sunmcDir + File.separator + fileNames[i];
            String backupString = origString + ".bak." + myResources.getString("patchName") +"-" + myResources.getString("patchID");
	        
	        File origFile = new File(origString);
	        File backupFile = new File(backupString);
            
            try {
	        if(!copyFile(backupFile, origFile)) {
		        JOptionPane.showMessageDialog(
		            this,
		            "Could NOT backup files !\n" + origString, 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
	        }
            } catch (IOException io_ex) {
            //    System.out.println(io_ex.getMessage());
		        JOptionPane.showMessageDialog(
		            this,
		            "Backup files FAILED!\n" + origString, 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
            }
	        /* DOES NOT WORK IF FILE ATTRIBUTE IS READ-ONLY !!!
	        if(!origFile.renameTo(backupFile)) {
		        JOptionPane.showMessageDialog(
		            this,
		            "Could NOT backup files !\n" + origString, 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return;
	        }
	        */
        }
	    return true;
	}
	
	public boolean deleteOldFiles() {
        for(int i=0; i<fileNames.length; i++) {
            String origString = sunmcDir + File.separator + fileNames[i];
	        File origFile = new File(origString);
            
            try {
	        if(!origFile.delete()) {
		        JOptionPane.showMessageDialog(
		            this,
		            "Could NOT delete files !\n" + origString, 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
	        }
            } catch (Exception ex) {
              //  System.out.println(ex.getMessage());
		        JOptionPane.showMessageDialog(
		            this,
		            "Delete files FAILED!\n" + origString, 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
            }
        }
        return true;
	}


public boolean copyBackupFiles() {
        for(int i=0; i<fileNames.length; i++) {
            
            String destString = sunmcDir + File.separator + fileNames[i];
            String srcString = sunmcDir + File.separator + fileNames[i] + ".bak." +  myResources.getString("patchName") +"-" + myResources.getString("patchID");
            
		//	System.out.println("dest String " + destString);
		//	System.out.println("src String " +  srcString);
			 
            File destFile = new File(destString);
            File srcFile = new File(srcString);
            
            try {
                if(!copyFile(destFile, srcFile)) {
		            JOptionPane.showMessageDialog(
		                this,
		                myResources.getString("copyFailed") + srcFile.toString(), 
		                "Error", 
		                JOptionPane.ERROR_MESSAGE );
    		        
		            return false;
                }
            } catch (IOException io_ex) {
          //      System.out.println(io_ex.getMessage());
		        JOptionPane.showMessageDialog(
		            this,
		            myResources.getString("copyFailed") + srcFile.toString(), 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
            }
            
            int step = 100/fileNames.length;
            int progress = 0;
            
            if(i == fileNames.length - 1) {
                progress = 100;
                InstallProgressBar.setValue(progress);
                InstallProgressBar.setString(progress + "%");
		        
		        JOptionPane.showMessageDialog(
		            this,
		            myResources.getString("uninstallcomplete"), 
		            "Info", 
		            JOptionPane.INFORMATION_MESSAGE);
		        
		        InstallProgressBar.setVisible(false);
            }
            else {
                progress = step * (i+1);
                InstallProgressBar.setValue(progress);
                InstallProgressBar.setString(progress + "%");
            }
			try {
			        srcFile.delete();
                 } catch (Exception ex) {
            //          System.out.println(ex.getMessage());
		              JOptionPane.showMessageDialog(
		              this,
		              myResources.getString("copyFailed") + srcString, 
		              "Error", 
		              JOptionPane.ERROR_MESSAGE );
		              return false;
            }
        }
		return true;
	}


	public boolean copyNewFiles() {
        for(int i=0; i<fileNames.length; i++) {
            
            String destString = sunmcDir + File.separator + fileNames[i];
            String srcString = sourceDir + File.separator + fileNames[i];
            
            File destFile = new File(destString);
            File srcFile = new File(srcString);
            
            try {
                if(!copyFile(destFile, srcFile)) {
		            JOptionPane.showMessageDialog(
		                this,
		                myResources.getString("copyFailed") + srcFile.toString(), 
		                "Error", 
		                JOptionPane.ERROR_MESSAGE );
    		        
		            return false;
                }
            } catch (IOException io_ex) {
              //  System.out.println(io_ex.getMessage());
		        JOptionPane.showMessageDialog(
		            this,
		            myResources.getString("copyFailed") + srcFile.toString(), 
		            "Error", 
		            JOptionPane.ERROR_MESSAGE );
		        
		        return false;
            }
            
            int step = 100/fileNames.length;
            int progress = 0;
            
            if(i == fileNames.length - 1) {
                progress = 100;
                InstallProgressBar.setValue(progress);
                InstallProgressBar.setString(progress + "%");
		        
		        JOptionPane.showMessageDialog(
		            this,
		            myResources.getString("complete"), 
		            "Info", 
		            JOptionPane.INFORMATION_MESSAGE);
		        
		        InstallProgressBar.setVisible(false);
            }
            else {
                progress = step * (i+1);
                InstallProgressBar.setValue(progress);
                InstallProgressBar.setString(progress + "%");
            }
        }
		return true;
	}
	
    /**
     * Converts a comma-delimited list of String into a String array.
     * 
     * @param	list	a comma-delimited list of String
     * @return	a String array
     */
    private String[] listToArray(String list) {
	    Vector v = new Vector();
	    StringTokenizer st = new StringTokenizer(list, ",");
	    
	    while (st.hasMoreTokens()) {
	        v.addElement((String)st.nextToken());
	    }
	    
	    String[] array = new String[v.size()];
	    v.copyInto(array);
	    
	    return array;
    }
    
    public String[] runCommand(String ssCmd, boolean isInput) {
	    try {
	        Process p = Runtime.getRuntime().exec(ssCmd);
	        String[] lines;
	        
	        if (isInput)
		        lines = readStream(new InputStreamReader(p.getInputStream()));
	        else
		        lines = readStream(new InputStreamReader(p.getErrorStream()));
    	
	        return lines;
	    
	    } catch (Exception e) {
	        return (new String[] {});
	    }
    }
    
    public String[] readStream(Reader oReader) throws Exception {
	    BufferedReader in = null;
	    String line;
	    Vector vResults = new Vector();
	    
	    try {
	        in = new BufferedReader(oReader);
	        while ((line = in.readLine()) != null) {
		        vResults.addElement(line);
	        }
	    } catch (Exception e) {
	        throw new Exception(e.getMessage());
	    } finally {
	        try {
	    	    in.close();
	        } catch (Exception e) {}
	    }

	    String[] ssResults = new String[vResults.size()];
	    vResults.copyInto(ssResults);
	    return ssResults;
    }
    
    /**
     * Copies source file to destination file.
     * @throws IOException
     */
    public boolean copyFile(File destfile, File srcfile) throws IOException {
        byte[] bytearr = new byte[512];
        int len = 0;
        
        FileInputStream input = new FileInputStream(srcfile);
        FileOutputStream output = new FileOutputStream(destfile);
        
        try {
            while ((len = input.read(bytearr)) != -1) {
                output.write(bytearr, 0, len);
            }
        } catch (FileNotFoundException fnf_exc) {
            System.out.println("File Not Found: " + srcfile);
            System.out.println(fnf_exc.getMessage());
            return false;
        } finally {
            input.close();
            output.close();
        }
        return true;
    }

    /**
    * Method that implements the following:
    * 1. Check if SunMC3.0 is installed;
    * 2. Query Widnows Registry for SunMC3.0 location.
    */
	public static void main(String args[]) {
	    WelcomeView welcomeView = new WelcomeView();
	    
			welcomeView.setVisible(true);
		
	}

}