/*
 * 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.accesstracking2;


import java.util.HashMap;
import java.util.Map;

import scone.netobjects.Access;


/**
 * This class stores a map of keys, containing userId, parent frame name and
 * frame name. Each key object is mapped to a list, storing the visited
 * Access objects in order of visiting.
 * It can be instanciated only once (Singleton pattern).
 *
 * @author Torsten Hass
 */

class BrowserHistory {
    private static BrowserHistory _instance = null;
    private Map map;
    private FrameHistory frameHistory;

    /**
     * Get a sole instance of BrowserHistory, using the Singleton pattern.
     */
    static BrowserHistory getInstance() {
        if (_instance == null) {
            _instance = new BrowserHistory();
            // System.out.println("New instance of bH");
        } else {}
        return _instance;
    }

    private BrowserHistory() {
        map = new HashMap();
    }

    /**
     * returns true if the key is already known.
     * @param key The String to be tested
     * @return True if the string exists.
     */
    boolean contains(String key) {
        return map.containsKey(key);
    }

    /**
     * This Method adds a new Access object to the history list of
     * a specific key.
     * If this key does not exist, the key is added to the map and
     * the Access object is stored in a new list.
     * @param key The key to identify user and browser frame
     * @param a The Access object to be added to list
     */
    void add(String key, Access a) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.add(a);
            // System.out.println("BrowserHistory: added Acceess object to " + key);
        } else {
            frameHistory = new FrameHistory();
            map.put(key, frameHistory);
            frameHistory.add(a);
            // System.out.println("BrowserHistory: created new key: " + key);
            // System.out.println("BrowserHistory: added Access object to " + key);
        }
    }


    /**
     * Get position and Access object a in history - looks backward...
     * @param key The key to identify user and browser frame
     * @param frameName
     * @return distance of position and a in history
     */
    int getPosition(String key, Access a) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getPosition(a);
        } else {
            return 0;
        }
    }


    /**
     * @param key The key to identify user and browser frame
     */
    int getHistoryLength(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getHistoryLength();
        } else {
            return 0;
        }
    }


    /**
     * Tests if a given Access object is part of the history list
     * @param key The key to identify user and browser frame
     * @param a The Access object to be searched in the list
     * @return true if a was found
     */
    boolean contains(String key, Access a) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.contains(a);
        } else {
            // System.out.println("BrowserHistory: Key: " + key + " does not exist");
            return false;
        }
    }

    /**
     * Creates a Key value that identifies the browser frame
     * Puts userId as an 16 digit string and parent frame name together and
     * returns it. If the page contains no frames and so parentFrameName is
     * empty, frameName is used.
     * @param userId
     * @param parentFrameName
     * @param frameName
     * @return All params in one string
     */
    String createKey(String userId, String parentFrameName, String frameName) {
        int counter;
        String key = "";

        // convert UserId to a 16 character string
        for (counter = userId.length(); counter < 8; counter++) {
            key += "0";
        }
        key += userId;
        // System.out.println("UserId = " + key);
        if (!parentFrameName.equals("")) {
            key += parentFrameName;
        }
        key += frameName;
        return key;
    }


    /**
     * Set lastAction
     * @param key The key to identify user and browser frame
     * @param lastAction Bit array that holds reason for last page change
     */
    void setLastAction(String key, int lastAction) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastAction(lastAction);
            // System.out.println("LastAction of key: " + key + " set to: " + lastAction);
        }
    }

    /**
     * Get lastAction
     * @param key The key to identify user and browser frame
     * @return bit Array that holds reason for last new page
     */
    int getLastAction(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastAction();
        } else {
            return -1;
        }
    }

    /**
     * Set lastLinkType
     * @param key The key to identify user and browser frame
     * @param lastLinkType Bit array that holds the type of the last clicked link...
     */
    void setLastLinkType(String key, int lastLinkType) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastLinkType(lastLinkType);
        }
    }
    
    /**
     * Get last sotred link type...
     * @param key The key to identify user and browser frame
     * @return int link type
     */
    int getLastLinkType(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastLinkType();
        } else {
            return 0;
        }
    }
    
    /**
     * Set lastLinkPos
     * @param key The key to identify user and browser frame
     * @param lastLinkPos as string
     */
    void setLastLinkPos(String key, String lastLinkPos) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastLinkPos(lastLinkPos);
        }
    }
    
    /**
     * Get last sotred link position...
     * @param key The key to identify user and browser frame
     * @return String link position
     */
    String getLastLinkPos(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastLinkPos();
        } else {
            return "";
        }
    }
    
    /**
     * Set lastWindowSize
     * @param key The key to identify user and browser frame
     * @param lastLinkPos as string
     */
    void setLastWindowSize(String key, String lastWindowSize) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastWindowSize(lastWindowSize);
        }
    }
    
    /**
     * Get last sotred link position...
     * @param key The key to identify user and browser frame
     * @return String link position
     */
    String getLastWindowSize(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastWindowSize();
        } else {
            return "";
        }
    }

    /**
     * Set last link anchor text
     * @param key The key to identify user and browser frame
     * @param lastLinkAnchor as string
     */
    void setLastLinkAnchor(String key, String lastLinkAnchor) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastLinkAnchor(lastLinkAnchor);
        }
    }
    
    /**
     * Get last sotred link anchor text...
     * @param key The key to identify user and browser frame
     * @return String link position
     */
    String getLastLinkAnchor(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastLinkAnchor();
        } else {
            return "";
        }
    }

    /**
     * Set last link title
     * @param key The key to identify user and browser frame
     * @param lastLinkPos as string
     */
    void setLastLinkTitle(String key, String lastLinkTitle) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastLinkTitle(lastLinkTitle);
        }
    }
    
    /**
     * Get last sotred link Title...
     * @param key The key to identify user and browser frame
     * @return String link title
     */
    String getLastLinkTitle(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastLinkTitle();
        } else {
            return "";
        }
    }
    
    /**
     * Set lastReferrer
     * @param key The key to identify user and browser frame
     * @param lastReferrer the nodeId of the last referrer
     */
    void setLastReferrer(String key, String nodeId) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setLastReferrer(nodeId);
            // System.out.println("LastAction of key: " + key + " set to: " + lastAction);
        }
    }

    /**
     * Get last referrer
     * @param key The key to identify user and browser frame
     * @return NodeId of last referrer
     */
    String getLastReferrer(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastReferrer();
        } else {
            return null;
        }
    }


    /**
     * Get last entry of frame history list
     * @param key The key to identify user and browser frame
     * @return Access object
     */
    Access getLastEvent(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getLastEvent();
        } else {
            return null;
        }
    }


    /**
     * Get last entry of frame history list
     * @param key The key to identify user and browser frame
     * @param number of event.
     * @return Access object
     */
    Access getEventAt(String key, int i) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getEventAt(i);
        } else {
            return null;
        }
    }


    /**
     * removes the last count Access objects from history list.
     * @param key The key to identify user and browser frame
     * @param count Number of Access objects to remove
     */
    public void removeLastEntries (String key, int count) {
        if (map.containsKey(key)) {
           frameHistory = (FrameHistory)map.get(key);
           frameHistory.removeLastEntries(count);
        } 
    }


    /**
     * removes the FIRST count Access objects from history list.
     * @param key The key to identify user and browser frame
     * @param count Number of Access objects to remove
     */
    public void removeFirstEntries (String key, int count) {
        if (map.containsKey(key)) {
           frameHistory = (FrameHistory)map.get(key);
           frameHistory.removeFirstEntries(count);
        } 
    }



    /**
     * Set position to Access object a in history
     * @param key The key to identify user and browser frame
     * @param a The Access object to set it's position in history
     */
    void setPosition(String key, int pos) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            frameHistory.setPosition(pos);
        }
    }

    /**
     * get position in history
     * @param key The key to identify user and browser frame
     * @param a The Access object to set it's position in history
     */
    int getPosition(String key) {
        if (map.containsKey(key)) {
            frameHistory = (FrameHistory) map.get(key);
            return frameHistory.getPosition();
        }
        else
            return 0;
    }


    /**
     * Get frame history object to lock it with synchronized
     * If the FrameHistory does not exist, it is created
     * @param key The key to identify user and browser frame
     * @return The FrameHistory object
     */
    synchronized FrameHistory getFrameHistory(String key) {
        if (map.containsKey(key)) {
            return (FrameHistory) map.get(key);
        } else {
            frameHistory = new FrameHistory();
            map.put(key, frameHistory);
            return frameHistory;
        }
    }

}   

