/*
 * Scone - The Web Enhancement Framework
 * Copyright (C) 2004 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.accesstracking2;


import scone.netobjects.Access;
import scone.netobjects.AccessCache;
import scone.netobjects.AccessEvent;


/**
 * The methods of this class are called by AccessTrackingMeg. Every
 * message of the meg has its own method to evaluate the received
 * information and to create and change Access events.
 *
 * @author Torsten Hass
 * @author Harald Weinreich
 * @version 1.5, 20-Aug-2004
 */


public class EventDecoderGecko extends EventDecoder {
    // constants for bit array action, indicating the action
    // the user performed to get to this page

    protected final int MAXHISTORY = 50;  // Mozilla maximum history length

    protected BrowserHistory bh;
    protected int browserName;
    protected boolean accessEventExisted;
    protected boolean showMessages;

    public EventDecoderGecko() {
        bh = BrowserHistory.getInstance();
        accessEventExisted = false;
        browserName = GECKO;
    }

    /**
     * This method is called when LogApplet was started and sent it's
     * first information. With that information an AccessEvent is
     * created and the BrowserHistory is updated.
     *
     * @param userId
     * @param nodeId
     * @param start
     * @param frame
     * @param fragment Fragment part of the URL
     * @param query Query part of the URL
     * @param post The posted form data
     * @param referrerNodeId Last URL
     * @param parentFrameName Name of the parent frame
     * @param parentNodeId URL of the parent frame
     * @param history Number of Frames in page
     */
    void startEvent( 
                    String userId,
                    String nodeId,
                    long start,
                    String frame,
                    String fragment,
                    String query,
                    String post,
                    String referrerNodeId,
                    String parentFrame,
                    String parentNodeId,
					String windowSize,
					String clickPos,
                    int history ) {

        if (frame.equals("") || nodeId.equals("") ) {
            // System.out.println("START: Window name missing - probably an iframe!");
            return; // No frame name, no nodeID - not really an event...
        }
        
        // Create key of this browser window/frame
        String key = bh.createKey(userId, parentFrame, frame);

        // System.out.println("--- Methode Started");
        // Create a new Access event, test if the page comes from browser's
        // cache, store all data of the applet in the access event.
        Access a = AccessCache.get(userId, nodeId, start, frame);
        a.setReferrerNodeId(referrerNodeId);
        a.setParentFrameName(parentFrame);
        a.setParentFrameNodeId(parentNodeId);

        a.setAction(BROWSER_GECKO | a.getAction() );

        // Post data?
        if (post!=null && !post.equals("")) {
            a.setAction(FORMSUBMIT | a.getAction() );
            a.setPost(post);
            bh.setLastAction(key, 0);  // Delete last action
        }
        // Maybe there are get parameter too, but that does not mean, the user clicked submit...
        a.setQuery(query);

        if (bh.contains(key)) { // Does a history for this browser frame already exist?
            // bh.getLast(key,nodeId);

            int historyLength = bh.getHistoryLength(key);   // Length of history in Scone
            int eventPosition = bh.getPosition(key,a);      // Position of current event in history
            int position = bh.getPosition(key);             // Position of last event in history

            //System.out.println("userId        : "+userId );
            //System.out.println("nodeId        : "+nodeId );
            //System.out.println("start         : "+start  );
            //System.out.println("frame         : "+frame  );
            //System.out.println("fragment      : "+fragment  );
            //System.out.println("Last Node ID  : " + bh.getLastEvent(key).getNodeId());
            //System.out.println("Refer. Node ID: " + referrerNodeId);
            //System.out.println("Last Action   : " + bh.getLastAction(key));
            //System.out.println("Last Link Anchor: " + bh.getLastLinkAnchor(key));
            //System.out.println("Last Link Title : " + bh.getLastLinkTitle(key));
            //System.out.println("Last Link Posit.: " + bh.getLastLinkPos(key));
            //System.out.println("Last Window Size: " + bh.getLastWindowSize(key));
            //System.out.println(" Browser: Gecko [Mozilla/Firebird/Netscape 6ff]");

            //System.out.println("historyLength : "+historyLength );
            //System.out.println("history       : "+history       );
            //System.out.println("this eventPos : "+eventPosition+" xxxxxxxxxxxxxxxx");
            //System.out.println("last Pos      : "+position+" xxxxxxxxxxxxxxxx");

            // Ops! Skipped some events...
            if (history > historyLength + 1) {  
                System.out.println("Some Browser events were skipped!?!---------------");
                for (int i=historyLength; i < history ; i++) {
                    bh.add(key, new Access(userId,"",0,"") );  // Add dummy events...
                }
                a.setAction(HEURISTIC | a.getAction() );  // forward several steps...
                a.setStepsInHistory(history - historyLength);
            }

            // History limit of Mozilla reached!
            if (history >= MAXHISTORY) {  
                if (history == historyLength) {  // History same length
                    if (bh.getLastAction(key) == FORMSUBMIT)           // Submit was clicked
                        bh.removeFirstEntries(key, historyLength-MAXHISTORY+1);  // delete oldest event
                    else if (bh.getLastAction(key) == LINK)          // Link was clicked
                        bh.removeFirstEntries(key, historyLength-MAXHISTORY+1);  // delete oldest event
                    else if (eventPosition == 0 || eventPosition <= position - 16) // Unlikely that he went back more than 16 steps...
                        bh.removeFirstEntries(key, historyLength-MAXHISTORY+1);  // delete oldest event
                }
            }

            // read again... may have changed...
            historyLength = bh.getHistoryLength(key);   // Length of history in Scone
            eventPosition = bh.getPosition(key,a);      // Position of current event in history
            position = bh.getPosition(key);             // Position of last event in history
            //System.out.println("historyLength : "+historyLength );
            //System.out.println("this eventPos : "+eventPosition+" xxxxxxxxxxxxxxxx");
            //System.out.println("last Pos      : "+position+" xxxxxxxxxxxxxxxx");

            // History one longer - Add a new page
            if (history == historyLength + 1) {  
                a.setStepsInHistory(1);
                bh.add(key,a);  // New action event
                if (bh.getLastAction(key) == FORMSUBMIT) {
                    a.setAction(FORMSUBMIT | a.getAction() );  // Submit was clicked
                } else if (bh.getLastAction(key) == LINK) {
                    a.setAction(LINK | a.getAction() );  // Link was clicked
                    a.setLinkType(bh.getLastLinkType(key));
                    a.setLinkPos(bh.getLastLinkPos(key));
                    a.setLinkAnchor(bh.getLastLinkAnchor(key));
                    a.setLinkTitle(bh.getLastLinkTitle(key));
                    a.setLastWindowSize(bh.getLastWindowSize(key));
                } else {
                    if (bh.getLastEvent(key).getNodeId().equals(referrerNodeId) || !fragment.equals("")) {
                        a.setAction(LINK | HEURISTIC | a.getAction() );  // Link was probably clicked
                    }
                    if (bh.getLastReferrer(key).equals(referrerNodeId) && fragment.equals("")) { // Only if not fragment was clicked!
                        a.setAction(NEWURL | HEURISTIC | a.getAction() );  // Something else was done, same referrer as before!
                    }
                }                
            }
            // length did not change.. Maybe back button...?            
            if (historyLength == history) {  
                if (bh.getLastAction(key) == FORMSUBMIT) {
                    a.setAction(FORMSUBMIT | a.getAction() );  // Submit was clicked
                    a.setStepsInHistory(1);
                    bh.removeLastEntries(key, 1);
                    bh.add(key, a);  // New action event
                } else if (bh.getLastAction(key) == LINK) {
                    a.setAction(LINK | a.getAction() );  // Link was clicked
                    a.setLinkType(bh.getLastLinkType(key));
                    a.setLinkPos(bh.getLastLinkPos(key));
                    a.setLinkAnchor(bh.getLastLinkAnchor(key));
                    a.setLinkTitle(bh.getLastLinkTitle(key));
                    a.setLastWindowSize(bh.getLastWindowSize(key));
                    a.setAction(LINK | a.getAction() );  // Link was probably clicked
                    if (!bh.getLastEvent(key).getNodeId().equals(referrerNodeId))
                        a.setAction(HEURISTIC | a.getAction() );  // Link was probably clicked
                    a.setStepsInHistory(1);
                    bh.removeLastEntries(key, 1);
                    bh.add(key, a);  // New action event
                } else if (eventPosition == 0 && bh.getLastReferrer(key).equals(referrerNodeId)) {
                    // Not found!!! -> Hub and Spoke
                    a.setAction(LINK | HEURISTIC | a.getAction() );  // Link was probably clicked
                    a.setStepsInHistory(1);
                    bh.removeLastEntries(key, 1);
                    bh.add(key, a);  // New action event
                } else if (eventPosition == position) {
                    a.setStepsInHistory(0);
                    a.setAction(RELOAD | HEURISTIC | a.getAction() );  // page reloaded
                } else if (eventPosition <= position && eventPosition > 0 &&
                                (eventPosition > position - 2 ||  
                                (eventPosition > position - 16 && history < 50)) ) {  // Höchstens 16 und bei history == 50 mal ganz vorsichtig...
                	// backwards...
                    a.setAction(BACK | a.getAction() );  // back was probably clicked
                    if (( !bh.getLastReferrer(key).equals(referrerNodeId) && 
                          !bh.getEventAt(key,eventPosition).getReferrerNodeId().equals(referrerNodeId))
                        || !fragment.equals("")) { 
                        a.setAction(HEURISTIC | a.getAction() );  // back several steps...
                    }
                    if (eventPosition != position - 1) {
                        a.setAction(SKIPPED | HEURISTIC | a.getAction() );  // back several steps...
                    }
                	a.setStepsInHistory(eventPosition - position);
                    bh.setPosition(key,eventPosition);
                } else if (eventPosition > position) {
                	// forward...
                    a.setStepsInHistory(eventPosition - position);
                    a.setAction(NEXT | HEURISTIC | a.getAction() );  // back was probably clicked
                    bh.setPosition(key,eventPosition);
                }
            }            
            if (history < historyLength) {  
//                if (eventPosition == 0) {
                    if (bh.getLastAction(key) == FORMSUBMIT) {
                        a.setAction(FORMSUBMIT | a.getAction() );  // Submit was clicked
                		a.setStepsInHistory(1);
                    } else if (bh.getLastAction(key) == LINK) {
                        a.setAction(LINK | a.getAction() );  // Link was clicked
                		a.setStepsInHistory(1);
                        a.setLinkType(bh.getLastLinkType(key));
                        a.setLinkPos(bh.getLastLinkPos(key));
                        a.setLinkAnchor(bh.getLastLinkAnchor(key));
                        a.setLinkTitle(bh.getLastLinkTitle(key));
                        a.setLastWindowSize(bh.getLastWindowSize(key));
                    } else {
                        if (bh.getLastEvent(key).getNodeId().equals(referrerNodeId)) {
                            a.setAction(LINK | HEURISTIC | a.getAction() );  // Link was probably clicked
                    		a.setStepsInHistory(1);
                        }
                    }
                    bh.removeLastEntries(key, historyLength - history + 1);  // Delete last entries...
                    bh.add(key, a);  // New action event
//                } else if (eventPosition <= position) {
//                    System.out.println("ERROR --------------------11111111");
                    //a.setAction(BACK | HEURISTIC | a.getAction() );  // back was probably clicked
                    //if (eventPosition != position - 1) {
                    //    a.setAction(SKIPPED | a.getAction() );  // back several steps...
                    //    a.setStepsInHistory(position - eventPosition );
                    //}
                    //bh.setPosition(key,eventPosition);
//                } else if (eventPosition > position) {
//                    System.out.println("ERROR --------------------22222222");
                    //a.setAction(NEXT | HEURISTIC | a.getAction() );  // back was probably clicked
                    //bh.setPosition(key,eventPosition);
//                } 
            }            
                
        }
        else // New browser window
        {
    		a.setStepsInHistory(1);
            if ( parentFrame.equals("") && parentNodeId.equals("") && frame.startsWith("SCONE")) {
                a.setAction(NEWWINDOW | a.getAction() );
                if (history > 1) {
                    // System.out.println("---------------------------------------------------------------");
                    // System.out.println("---- Browser history not empty! Please restart browser!!! -----");
                    // System.out.println("---------------------------------------------------------------");
                }
            } else {
                a.setAction(NEWFRAME | a.getAction() );
                String parentKey = bh.createKey(userId, "", parentFrame);
                bh.setLastAction(parentKey, 0);  // Delete last action of parent frame to avoid wrong events...
            }
            if (history > 1) {
                for (int i=1; i < history ; i++) {
                    bh.add(key, new Access(userId,"",0,"") );  // Add dummy events...
                }
            }
            bh.add(key, a);  // New browser Frame and new action event
        }

        // set fragment = "#top" etc.
        if (!fragment.equals("")) {
            a.setFragment(fragment);
            a.setAction(FRAGMENT | a.getAction() );
        }

        // a.setAction(action);
        // a.store(); -> Save if user leaves a page...
        AccessCache.broadcastEvent(new AccessEvent(a));   // Now broadcast event again with Action infos...!
        
        bh.setLastReferrer(key, referrerNodeId);
        bh.setLastAction(key, 0);  // Delete last action
        bh.setLastLinkType(key, 0);  // Delete last type
        bh.setLastLinkTitle(key, "");  // Delete 
        bh.setLastLinkAnchor(key, "");  // Delete 
        bh.setLastLinkPos(key, "");  // Delete 
        bh.setLastWindowSize(key, "");  // Delete 
    }

}
