/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

package installer;

import java.net.URLDecoder;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.net.*;

public class InstUtil {

    public static File buildSversionLocation() throws IOException {
		File theFile = null;
        StringBuffer str = new StringBuffer();
        str.append(System.getProperty("user.home"));
        str.append(File.separator);
		StringBuffer thePath = new StringBuffer(str.toString());

        String os = System.getProperty("os.name");

		if (os.indexOf("Windows") != -1) {
			boolean bSVersionInHomeDir = new File(thePath.toString() + "sversion.ini").exists();

			if (!bSVersionInHomeDir) {
				thePath.append("Application Data");
				thePath.append(File.separator);
			}
			theFile = findVersionFile(new File(thePath.toString()));
        } else if (os.indexOf("SunOS") != -1) {
            thePath.append(".sversionrc");
			theFile = new File(thePath.toString());
        } else if (os.indexOf("Linux") != -1) {
            thePath.append(".sversionrc");
			theFile = new File(thePath.toString());
		}

		if (theFile == null)
		{
			throw new IOException("Could not locate the OpenOffice settings file.\nAre you sure StarOffice is installed on your system?");
		}
		if  (!theFile.exists())
		{
			throw new IOException("Could not locate the OpenOffice settings file.\nAre you sure StarOffice is installed on your system?");
		}
        return theFile;
    }



    public static boolean hasNetbeansInstallation() {
        boolean result = false;
        try
        {
            result = checkForSupportedVersion( getNetbeansLocation(), versions );

            if (result == false)
                System.out.println("No supported version of NetBeans found.");
        }
        catch ( IOException ioe )
        {
            System.err.println("Exception caught trying to determine netbeans installation: " + ioe );
            ioe.printStackTrace();
            result = false;
        }
        return result;
    }

    private static boolean checkForSupportedVersion( Properties installs, String[] supportedVersions )
    {
        if ( installs != null )
        {
            for ( int index = 0; index < supportedVersions.length; index++ )
            {
                String key = supportedVersions[ index ];
                String path = null;
                if ( ( path = installs.getProperty(key) ) != null )
                {
                    // at least one supported version for netbeans present, so return;
                    return true;
                }

            }
        }
        return false;
    }


    public static boolean hasJeditInstallation() {
        boolean result = false;
        try
        {
            result = checkForSupportedVersion( getJeditLocation(), versions );
            if ( !result )
            {
                System.out.println("No supported version for JEdit found.");
            }
        }
        catch ( IOException ioe )
        {
            System.err.println("Exception caught trying to determine jedit installation: " + ioe );
            ioe.printStackTrace();
            result = false;
        }
        return result;
    }



    public static Properties getNetbeansLocation() throws IOException {
	File theFile = null;
	Properties results = new Properties();

	StringBuffer str = new StringBuffer();
        str.append(System.getProperty("user.home"));
        str.append(File.separator);
	StringBuffer thePath = new StringBuffer(str.toString());

        String os = System.getProperty("os.name");

	if (os.indexOf("Windows") != -1) {
		//theFile = findVersionFile(new File(str.toString()));
		thePath.append(".netbeans");
		//theFile = new File(thePath.toString());
        } else if (os.indexOf("SunOS") != -1) {
		thePath.append(".netbeans");
		//theFile = new File(thePath.toString());
        } else if (os.indexOf("Linux") != -1) {
		thePath.append(".netbeans");
		//theFile = new File(thePath.toString());
	}

	if ( thePath.toString().indexOf( ".netbeans" ) == -1 )
		return null;
	else if ( new File( thePath.append( File.separator+"3.4"+File.separator ).toString() ).isDirectory() ) {

		System.out.println( "Found NetBeans 3.4 user directory: " + thePath );
		File netbeansLogFile = new File( thePath.toString() + File.separator + "system" + File.separator + "ide.log" );
		if( netbeansLogFile.exists() ) {
			String installPath = getNetbeansInstallation( netbeansLogFile );
			File f = new File(installPath);
			results.put("NetBeans 3.4", f.getPath()+File.separator);
			System.out.println( "NetBeans Installation directory: " + f.getPath());
		}
		else {
			System.out.println( "No NetBeans log file found" );
                        return null;
		}
	}
        else
        {
	    System.out.println( "No NetBeans user directory found" );
	    return null;
        }


	return results;
    }



    public static Properties getJeditLocation() throws IOException {

	/*if( !hasJeditInstallation() ) {
		System.out.println( "No Jedit found (line195 InstUtil");
		return null;
	}*/

	File theFile = null;
	Properties results = new Properties();

	StringBuffer str = new StringBuffer();
        str.append(System.getProperty("user.home"));
        str.append(File.separator);
	StringBuffer thePath = new StringBuffer(str.toString());

        String os = System.getProperty("os.name");
        thePath.append(".jedit");
	//System.out.println( ".jedit path " + thePath );

	File jeditLogFile = new File( thePath.toString() + File.separator + "activity.log" );
	if( jeditLogFile.exists() ) {
		String[] jeditDetails = getJeditInstallation( jeditLogFile );
		System.out.println( "getJeditLocation ) " + jeditDetails[0] );
		File f = new File(jeditDetails[0]);
		results.put("jEdit "+jeditDetails[1], jeditDetails[0]);
		System.out.println( "jeditDetails[0] is " + jeditDetails[0]);
	}
	else {
		System.out.println( "Prompt user for Jedit installation path" );
	}


	return results;
    }





    private static String getNetbeansInstallation( File logFile ) {
	    String installPath = "";
	    try {
	    BufferedReader reader = new BufferedReader(new FileReader(logFile));

	    for (String s = reader.readLine(); s != null; s = reader.readLine()) {
		s.trim();
		if( s.indexOf( "IDE Install" ) != -1 ) {
			int pathStart = s.indexOf( "=" ) + 2;
			//System.out.println( "pathStart " + pathStart );
			installPath = s.substring( pathStart, s.length() );
			//System.out.println( "installPath 1" + installPath );
			int pathEnd = installPath.indexOf( ";");
			//System.out.println( "pathEnd " + pathEnd );
			installPath = installPath.substring( 0, pathEnd ) +File.separator;
			//System.out.println( "pathStart " + pathStart );
			//int pathEnd = s.indexOf( ";");
			//System.out.println( "pathEnd " + pathEnd );
			//System.out.println( "s is " + s + " and " + s.length() + " long" );
			//installPath = s.substring( pathStart, pathEnd - 1 );
			installPath.trim();
			break;
		}
	    }
	    }
	    catch( IOException ioe ) {
		System.out.println( "Error reading Netbeans location information" );
            }
	    //catch( FileNotFoundException fnfe ) {
		//System.out.println( "NetBeans ide.log FileNotFoundException" );
	    //}

	    return installPath;
    }


    private static String[] getJeditInstallation( File logFile ) {
	    String[] jeditDetails = new String[2];
	    try {
	    BufferedReader reader = new BufferedReader(new FileReader(logFile));
	    String installPath = "";
	    String version = "";

	    for (String s = reader.readLine(); s != null; s = reader.readLine()) {
		s.trim();
		if( s.indexOf( "jEdit home directory is" ) != -1 ) {
			int pathStart = new String( "[message] jEdit: jEdit home directory is " ).length();
			//System.out.println( "pathStart " + pathStart );
			installPath = s.substring( pathStart, s.length() ) +File.separator;
			System.out.println( "installPath 1" + installPath );
			//int pathEnd = installPath.indexOf( ";");
			//System.out.println( "pathEnd " + pathEnd );
			//installPath = installPath.substring( 0, pathEnd ) +File.separator;
			//System.out.println( "pathStart " + pathStart );
			//int pathEnd = s.indexOf( ";");
			//System.out.println( "pathEnd " + pathEnd );
			//System.out.println( "s is " + s + " and " + s.length() + " long" );
			//installPath = s.substring( pathStart, pathEnd - 1 );
			installPath.trim();
			//System.out.println( "installPath 2 " + installPath );
			//break;
			jeditDetails[0] = installPath;
		}
		if( s.indexOf( "jEdit: jEdit version" ) != -1 ) {
			int versionStart = s.indexOf( "version" ) + 8;
			System.out.println( "versionStart is: " + versionStart );
			version = s.substring( versionStart, s.length() );
			version.trim();
			System.out.println( "jEdit version is: " + version );
			jeditDetails[1] = version;
		}
	    }
	    }
	    catch( IOException ioe ) {
		System.out.println( "Error reading Jedit location information" );
            }
	    //catch( FileNotFoundException fnfe ) {
		//System.out.println( "Jedit activity.log FileNotFoundException" );
	    //}

	    return jeditDetails;
    }



	public static File findVersionFile(File start)
	{
		File versionFile = null;

		File files[] = start.listFiles(new VersionFilter());
		if (files.length == 0)
		{
			File dirs[] = start.listFiles(new DirFilter());
			for (int i=0; i< dirs.length; i++)
			{
				versionFile = findVersionFile(dirs[i]);
				if (versionFile != null)
				{
					break;
				}
			}
		}
		else
		{
			versionFile = files[0];
		}

		return versionFile;
	}

    public static boolean verifySversionExists(File sversionFile) {
        if (!sversionFile.exists())
            return false;
        return true;
    }

    public static Properties getOfficeVersions(File sversionFile) throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(sversionFile));
        Vector values;
        String sectionName = null;
        Properties results = new Properties();

        for (String s = reader.readLine(); s != null; s = reader.readLine()) {
            s.trim();
            //System.out.println(s);
            if (s.length() == 0)
                continue;
            if (s.charAt(0) == '[') {
                sectionName = s.substring(1, s.length() - 1);
                //System.out.println(sectionName);
                continue;
            }
            if ((sectionName != null) && sectionName.equalsIgnoreCase("Versions")) {
                int equals = s.indexOf( "=" );
		String officeName = s.substring(0, equals );

		String instPath = s.substring(equals + 8, s.length());
		String [] parts = new String[2];
		parts[0] = officeName;
		parts[1] = instPath + File.separator;
		//System.out.println( "InstUtil officeName " + officeName );
		//System.out.println( "InstUtil instPath " + instPath );

		//String [] parts = s.split("=");
                if (parts.length == 2) {
                    //ver.version = parts[0].trim();
                    //File f = new File(parts[1].trim());
		    //results.put(parts[0].trim(), f.getPath());
		    try {
                        URL url = new URL("file://" + parts[1].trim());
			String opSys =System.getProperty("os.name");
			if (opSys.indexOf("Windows")!=-1){
				String windowsPath = URLDecoder.decode( url.getPath() );
				boolean firstSlash = true;
				while( windowsPath.indexOf("/") != -1 ) {
					int forwardSlashPos = windowsPath.indexOf("/");
					String firstPart = windowsPath.substring( 0, forwardSlashPos );
					String lastPart = windowsPath.substring( forwardSlashPos + 1, windowsPath.length() );
					if( firstSlash ) {
						windowsPath = lastPart;
						firstSlash = false;
					}
					else {
						windowsPath = firstPart + "\\" + lastPart;
					}
				}
				int lastSlash = windowsPath.lastIndexOf("\\");
				windowsPath = windowsPath.substring( 0, lastSlash );
				results.put( parts[0].trim(), windowsPath );
			}
			else {
				//System.err.println( " InstUtil URLDecoder " + URLDecoder.decode(url.getPath()) );
				results.put(parts[0].trim(), URLDecoder.decode(url.getPath()));
			}
                        //File f = new File(url);

			//.sversion: OpenOffice.org 643=file:///scriptdev/neil/ScriptFrameOpenoffice1.0.1
			// parts = Installation name. f.getPath = Installation path
                        //results.put(parts[0].trim(), f.getPath());

                        //results.put(parts[0].trim(), URLDecoder.decode(url.getPath()));
			//results.put( parts[0].trim(), windowsPath );

                    }
                    catch (MalformedURLException eSyntax) {
                        //throw new IOException("Error while reading version information");
			results.put(parts[0].trim(), parts[1].trim());
			//System.out.println(parts[0].trim() + " : " + parts[1].trim());
			System.err.println("GotHereException");
                    }
                }
                else {
                    System.out.println("not splitting on equals");
                }
            }
        }

        return results;
    }

    public static String getJavaVersion() {
        return System.getProperty("java.version");
    }

    public static boolean isCorrectJavaVersion() {
        if (System.getProperty("java.version").startsWith("1.4"))
            return true;
        return false;
    }

    public static void main(String args[]) {
        InstUtil inst = new InstUtil();
		File f = null;
        try
		{
			f = inst.buildSversionLocation();
		}
		catch (IOException e)
		{
			e.printStackTrace();
			System.out.println(e.getMessage());
		}
        if (!inst.verifySversionExists(f)) {
            System.err.println("Problem with sversion.ini");
        }
        try {
            Properties vers = inst.getOfficeVersions(f);
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println(e);
        }
        System.out.println(inst.getJavaVersion());
        if (!inst.isCorrectJavaVersion()) {
            System.err.println("Not correct Java Version");
        }
    }

    public static final String [] versions = {"NetBeans 3.4", "jEdit 4.0.3", "jEdit 4.1pre5" };
    private static File tmpDir = null;
}



class DirFilter implements java.io.FileFilter
{
	public boolean accept(File aFile)
	{
		return aFile.isDirectory();
	}
}
class VersionFilter implements java.io.FileFilter
{
	public boolean accept(File aFile)
	{
		if (aFile.getName().compareToIgnoreCase("sversion.ini") == 0)
		{
			return true;
		}

		return false;
	}
}
