/*
 * Scone - The Web Enhancement Framework
 * Copyright (C) 2009 Harald Weinreich, Volkert Buchmann, Frank Wollenweber, Torsten Haß
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package scone.accesstracking;

import java.net.InetAddress;

import scone.proxy.GeneralResourceGenerator;
import scone.util.ErrorLog;
import scone.util.PersistentProperties;

public class AccessTracking extends scone.Plugin {
    private int resourcePort = 8088;
    private int connectionPort = 8472;
    private String sconeIP;
    protected static PersistentProperties props = new PersistentProperties("config/scone/accesstracking.xml");
    private Process ieSpyProcess;

    // requirements!
    public int getRequirements() {
        return CONSIDERLINKS | RESOURCEGENERATOR | RAS;       // Use CONSIDERLINKS if you want to get events if a user clicks on a link.
        // return NOREQUIREMENTS;
        // return RESOURCEGENERATOR;  // Enable the Resourcegenerator to load the applet from
    }

    public int getRasPort() {
        if (props == null) {
            System.out.print("accesstracking.xml not found.\n          ");
        }
        try {
            // get port number for connections from applet
            if (props.get("Acesstracking1: Scone port for AppletConnection") != null) {
                connectionPort = Integer.parseInt(props.get("Acesstracking1: Scone port for AppletConnection"));
                if ((connectionPort < 1024) || (connectionPort > 65535)) {
                    throw new NumberFormatException();
                }
            } else {
                throw new NumberFormatException();
            }
        } catch (NumberFormatException e2) { // Acesstracking1: Scone port for AppletConnection is not a valid number
            System.out.print("\"Acesstracking1: Scone port for AppletConnection\" is not a valid number. Using defalt.\n          ");
        } catch (Exception e1) {
            System.out.print("\"Acesstracking1: Scone port for AppletConnection\" not found in Properties. Using defalt.\n          ");
        }
        return connectionPort;
    }

    /**
     * Initialize Accesstracking: read local address, ras port etc, set up ras etc.
     */
    public void init() {
        System.out.print("\n          ");
        try {
            // Allow AppletConnector to access plugin properties
            ConfigAccess ca = ConfigAccess.getInstance();

            ca.setPlugin(this);

            // Get "Acesstracking1: Scone IP for AppletConnection" for general resource generator from Properties
            try {
                if (props.get("Acesstracking1: Scone IP for AppletConnection") != null
                        && props.get("Acesstracking1: Scone IP for AppletConnection") != "") {
                    sconeIP = props.get("Acesstracking1: Scone IP for AppletConnection").trim();
                } else {
                    sconeIP = InetAddress.getLocalHost().getHostAddress();
                }
                System.out.print("Using "+sconeIP+" as Scone address for RAS connection\n          ");
            } catch (Exception e1) {
                sconeIP = "127.0.0.1";
                System.out.print("\"Acesstracking1: Scone IP for AppletConnection\" not found in properties. Using 127.0.0.1\n          ");
            }
            // Get port number for general resource generator from properties
            try {
                if (props.get("Acesstracking1: WBI proxy port") != null) {
                    resourcePort = Integer.parseInt(props.get("Acesstracking1: WBI proxy port"));
                    if ((resourcePort < 1024) || (resourcePort > 65535)) {
                        throw new NumberFormatException();
                    }
                } else {
                    throw new NumberFormatException();
                }
            } catch (NumberFormatException e2) { // resource port is not a valid number
                System.out.print("\"Acesstracking1: WBI proxy port\" is not a valid number. Using defalt.\n          ");
            } catch (Exception e1) {
                System.out.print("\"Acesstracking1: WBI proxy port\" not found in Properties. Using defalt.\n          ");
            }

            GeneralResourceGenerator.addPath("http://" + sconeIP + ":" + resourcePort + "/accesstracking/res", "resources/accesstracking");
            // As IE6 etc. are buggy and sometimes local paths are omitted, we also need this line... 
            GeneralResourceGenerator.addPath("/accesstracking/res", "resources/accesstracking");

            // This adds a little JavaScript block to the beginning of HTML-File, that
            // stores the actual time for calculating load time and staytime
            TimeStoreScriptAdder tssAdder = new TimeStoreScriptAdder();
            tssAdder.setup("AccessTracking: TimeStoreScriptAdder", HTDOCCONDITION, 80);  // After the ParsingMeg (90)!
            addMeg(tssAdder);

            // This adds the call for the external JavaScript file to HTML file
            JavaScriptAdder jAdder = new JavaScriptAdder();

            jAdder.setup("AccessTracking: JavaScriptAdder", HTDOCCONDITION, 60);
            addMeg(jAdder);

            // This adds onLoad and onUnload-Events to the BODY-Tag.
            // onload is necessary, as oterwise sometimes no access-eventa are created.
            // -> The picture _scone_axxxxx bzw. /_start is not loaded!?!
            // unLoad sends a event if a user leaves a page.
            BodyEventAdder beAdder = new BodyEventAdder();

            beAdder.setup("AccessTracking: BodyEventAdder", HTDOCCONDITION, 60);
            addMeg(beAdder);

            // The LinkEvents create events if a user click on a link.
            // This slows down parsing of thepage, as "CONSIDERLINKS" has to be used.
            LinkEventAdder leAdder = new LinkEventAdder();

            leAdder.setup("AccessTracking: LinkEventAdder", HTDOCCONDITION, 60);
            addMeg(leAdder);

            // The onsubmit events of forms creates an event if a user submits a form.
            FormSubmitEventAdder fsAdder = new FormSubmitEventAdder();

            fsAdder.setup("AccessTracking: FormSubmitEventAdder", HTDOCCONDITION, 60);
            addMeg(fsAdder);

            AccessTrackingMeg accessTrackingMeg = new AccessTrackingMeg(this);

            accessTrackingMeg.setup("AccessTracking: AccessTrackingMeg", "host~tracking.scone.de", 100);
            addMeg(accessTrackingMeg);

            // Use this meg to log also access to Non-html-pages.
            if (props.get("Create events for non-HTML documents") != null
                    && props.get("Create events for non-HTML documents").equals("true")) {
                NoHTMLAccessMeg noHTML = new NoHTMLAccessMeg(this);
                noHTML.setup("AccessTracking: NoHTMLAccessMeg", NO_HTDOCCONDITION, 60);
                addMeg(noHTML);
            }

            try {
                if (props.get("Acesstracking1: Show FrameAccessTestGui") != null) {
                    if (props.get("Acesstracking1: Show FrameAccessTestGui").equals("true")) {
                        FrameAccessTest fat = new FrameAccessTest();

                        fat.start();
                    }
                }
            } catch (Exception e1) {
                System.out.print("\"FrameAccessTestGui\" not found in Properties. Using defalt.\n          ");
            }

            try {
                if (props.get("Acesstracking1: Scone port for AppletConnection") != null) {
                    connectionPort = Integer.parseInt(props.get("Acesstracking1: Scone port for AppletConnection"));
                    if ((connectionPort < 1024) || (connectionPort > 65535)) {
                        throw new NumberFormatException();
                    }
                } else {
                    throw new NumberFormatException();
                }
            } catch (NumberFormatException e2) { // Acesstracking1: Scone port for AppletConnection is not a valid number
                connectionPort = 8472;
                System.out.print("\"Acesstracking1: Scone port for AppletConnection\" is not a valid number. Using defalt.\n          ");
            } catch (Exception e1) {
                connectionPort = 8472;
                System.out.print("\"Acesstracking1: Scone port for AppletConnection\" not found in Properties. Using defalt.\n          ");
            }
            // AccessServer e = new AccessServer(connectionPort);
            // e.start();

            try {
                if (props.get("Acesstracking1: Enable IESpy").equals("true")) {// System.out.print("\nTrying to start IESpyWin...");
                    // ieSpyProcess = Runtime.getRuntime().exec("resources\\accesstracking\\IESpyWin.lnk");
                    // System.out.println("OK");
                }
            } catch (Exception e1) {
                System.out.print("Error while starting IESpyWin.\n          ");
            }

        } catch (Exception e) {
            ErrorLog.log(this, "init()", "Could not enable AccessTracking!", e);
        }

    }

    /**
     * returns the IP-Address of scone. Used e.g. für the RAS-Connection.
     */
    public String getSconeIP(){
        return sconeIP;
    }

    /**
     * returns the connection port used by RAS.
     */
    public int getConnectionPort(){
        return connectionPort;
    }

    /**
     * returns the resource port of scone, where to load the included HTML and JavaScript code. 
     * Should usually be 8088.
     */
    public int getResourcePort(){
        return resourcePort;
    }

    public void terminate() {// shut down IESpy
        // ieSpyProcess.destroy();
    }

}
