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


import java.sql.ResultSet;


/**
 * Access-Objects contain information about single access actions
 * See scone.examples.OberserverTestPlugin for an example how to use the acess-Events
 * 
 * @author Harald Weinreich
 * @author Volkert Buchmann
 * @author Torsten Hass
 */

public class Access extends TableRecord {
    public static final String COPYRIGHT = "(C) Harald Weinreich, Volkert Buchmann & Torsten Hass";

    // hier wird abgespeichert, wann und ob dieser Event vom Meg und oder vom Applet erzeugt
    // wurde mit der entsprechenden Zeit
    private int megStartTime;     // Zeit vom Browser per Imageload übergeben, diese kann von einem früheren Besuch der Seite stammen-> Hilf diesen Event zu identifizieren!
    private NetNode nodekeeper;   // Workaround to keep the netnode in the cache if the database is deactivated until the access event is dumped...
    private HtmlNode htmlnodekeeper;   // Workaround to keep the netnode in the cache if the database is deactivated until the access event is dumped...
    private boolean shown = false;  // Was this event already displayed?

    protected static DBTableAdapter dbTable;

    // set sql meta-data
    static {

        dbTable = new DBTableAdapter("AccessTable");
		
        /*

         dbTable.addField("userId",           dbTable.STRING, "",dbTable.KEY);
         dbTable.addField("nodeId",           dbTable.STRING, "",dbTable.KEY);
         dbTable.addField("time",             dbTable.NUMBER,"0",dbTable.KEY);
         dbTable.addField("frameName",        dbTable.STRING, "",dbTable.KEY);
         dbTable.addField("accessId",         dbTable.STRING, "",dbTable.KEY);
         dbTable.addField("parentAccessId",   dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("action",           dbTable.NUMBER,"0",dbTable.FIELD);
         dbTable.addField("fragment",         dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("query",            dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("post",           dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("parentFrameNodeId",dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("parentFrameName",  dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("referrerNodeId",   dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("linkId",           dbTable.STRING, "",dbTable.FIELD);
         dbTable.addField("linkType",         dbTable.NUMBER,"0",dbTable.FIELD);
         dbTable.addField("loadTime",         dbTable.NUMBER,"0",dbTable.FIELD);
         dbTable.addField("stayTime",         dbTable.NUMBER,"0",dbTable.FIELD);
         */

    }

    /**
     * Constructor: Create a new Access-Object with the necessary key values.
     * @param userId: The id of the user (from cookie)
     * @param nodeId: The current Node
     * @param time: The (start) time of the access
     * @param frameName: Name of the frame or window (given or generated by <I>Scone</I>)
     */
    public Access(String userId, String nodeId, long time, String frameName) {
        dbTable.init(this);
        fieldValues.put("userId", userId);
        fieldValues.put("nodeId", nodeId);
        fieldValues.put("time", String.valueOf(time));  // Warum geht fieldValues nicht?!?!?!
        fieldValues.put("frameName", frameName);
        fieldValues.put("accessId", SimpleUri.getHexHashCode(userId + "/" + nodeId + "/" + time + "+" + frameName));

        // Create pointers to the netnode and htmlnode
        nodekeeper = NetNodeCache.getById(nodeId);
        htmlnodekeeper = HtmlNodeCache.get(nodekeeper);

        // System.out.println("New Access Object: "+userId + ", " + nodeId + ", " + time + ", " + frameName);
        dbTable.dbInit(this);
    }

    /**
     * Constructor: Create a new Access-Object with all available values of a new access.
     * @param userId: The id of the user (from cookie)
     * @param nodeId: The current Node
     * @param time: The (start) time of the access
     * @param frameName: Name of the frame or window (given or generated by <I>Scone</I>)
     * @param fragment: The string after the #
     * @param query: Was it a query, e.g. to a search engine?
     * @param parentFrameNodeId: NodeId of the parent frame (if any)
     * @param parentFrameName: Name of the parent frame or window
     * @param referrerNodeId: The NodeId of the refferer page.
     */
    public Access(String userId, String nodeId, long time, String frameName, String fragment, String query,
            int parentFrameNodeId, String parentFrameName, int referrerNodeId) {
        this(userId, nodeId, time, frameName);
        fieldValues.put("fragment", fragment);
        fieldValues.put("query", query);
        fieldValues.put("parentFrameNodeId", String.valueOf(parentFrameNodeId));
        fieldValues.put("parentFrameName", parentFrameName);
        fieldValues.put("referrerNodeId", String.valueOf(referrerNodeId));
        fieldValues.put("accessId", SimpleUri.getHexHashCode(userId + "/" + nodeId + "/" + time + "+" + frameName));
    }

    /**
     * Constructor: Create a new Access-Object with all available values of a new access.
     * Is used to create an entry from server log.
     * @param userId: The id of the user (from IP-Address???)
     * @param nodeId: The current Node
     * @param time: The (start) time of the access
     * @param fragment: The string after the #
     * @param query: Was it a query, e.g. to a search engine?
     * @param referrerNodeId: The NodeId of the refferer page.
     * @param stay: The estimated time a user stayed on a page
     */
    public Access(String userId, String nodeId, long time, String fragment, String query, int referrerNodeId, long stay) {
        this(userId, nodeId, time, "ServerLog");
        fieldValues.put("fragment", fragment);
        fieldValues.put("query", query);
        fieldValues.put("referrerNodeId", String.valueOf(referrerNodeId));
        fieldValues.put("stay", String.valueOf(stay));
        store();
    }

    /**
     * Create Access-Object to a result of a db query.
     * @param results the ResultSet returnetd by the query.
     */
    public Access(ResultSet results) {
        dbTable.init(this);
        dbTable.fill(this, results);  // -> if there was a new row in results -> Fill user and hasRecordInDB=true
    }

    /**
     * sets the user id
     * @param userId
     */
    public void setUserId(String userId) {
        fieldValues.put("userId", userId);
    }

    /**
     * sets the node id
     * @param nodeId
     */
    public void setNodeId(String nodeId) {
        fieldValues.put("nodeId", nodeId);
    }

    /**
     * sets the time, when this page was started to load
     * @param time
     */
    public void setTime(long time) {
        fieldValues.put("time", String.valueOf(time));
    }

    /**
     * sets the frame name
     * @param frameName
     */
    public void setFrameName(String frameName) {
        fieldValues.put("frameName", frameName);
    }

    /**
     * sets the parent access id (only used if page is a frame of a frameset
     * @param parentAccessId
     */
    public void setParentAccessId(String parentAccessId) {
        fieldValues.put("parentAccessId", parentAccessId);
    }

    /**
     * sets the bit array 'action'
     * <P>
     * Bit  0:  link<BR>
     * Bit  1:  reference / fragment<BR>
     * Bit  2:  samePage / selflink<BR>
     * Bit  3:  submit<BR>
     * Bit  4:  reloaded<BR>
     * Bit  5:  back<BR>
     * Bit  6:  next<BR>
     * Bit  7:  jump over multiple steps in history<BR>
     * Bit  8:  new window<BR>
     * Bit  9:  bookmark<BR>
     * Bit 10:  linkbutton<BR>
     * Bit 11:  adressbar<BR>
     * Bit 12:  home<BR>
     * Bit 13:  history or favorites<BR>
     * Bit 14:  New Frame
     * Bit 15:  New Window
     * Bit 22: by hotkey<BR>
     * Bit 23: by html menu<BR>
     * Bit 24: by main menu<BR>
     * Bit 25: by toolbar button<BR>
     * Bit 26: by toolbar menu<BR>
     * Bit 27: on netscape / firefox<BR>
     * Bit 28: on explorer<BR>
     * Bit 29: on other gecko browser<BR>
     * Bit 30: by heuristic<BR>
     *
     * @param action
     */
    public void setAction(int action) {
        fieldValues.put("action", String.valueOf(action));
    }

    /**
     * sets the event as string
     * @param event
     */
    public void setEvent(String event) { fieldValues.put("event", event); }
    
    /**
     * sets the position of the last link
     * @param position
     */
    public void setLinkPos(String pos) { fieldValues.put("linkPos", pos); }
    
    /**
     * sets the link anchor string
     * @param anchor text
     */
    public void setLinkAnchor(String l) { fieldValues.put("linkAnchor", l); }
    
    /**
     * sets the title attribute of the last Link...
     * @param link title
     */
    public void setLinkTitle(String t) { fieldValues.put("linkTitle", t); }
    
    /**
     * sets the Size of the Browser window when the last link was clicked that lead to this page...
     * @param windowsize
     */
    public void setLastWindowSize(String w) { fieldValues.put("windowSize", w); }
    
    /**
     * sets the number of pages the user jumped back or next
     * @param stepsInHistory
     */
    public void setStepsInHistory(int stepsInHistory) {
        fieldValues.put("stepsInHistory", String.valueOf(stepsInHistory));
    }

    /**
     * sets the fragment string
     * @param fragment
     */
    public void setFragment(String fragment) {
        fieldValues.put("fragment", fragment);
    }

    /**
     * sets the query string
     * @param v the query
     */
    public void setQuery(String query) {
        fieldValues.put("query", query);
    }

    /**
     * sets the post string (when using POST method)
     * @param v the post string...
     */
    public void setPost(String post) {
        fieldValues.put("post", post);
    }

    /**
     * sets the parent frame node id
     * @param v the parentFrameName
     */
    public void setParentFrameNodeId(String parentFrameNodeId) {
        fieldValues.put("parentFrameNodeId", parentFrameNodeId);
    }

    /**
     * sets the frame name of the parent browser window
     * @param v the parentFrameName
     */
    public void setParentFrameName(String parentFrameName) {
        fieldValues.put("parentFrameName", parentFrameName);
    }

    /**
     * sets the referrer node id
     * @param v the referrerNodeId
     */
    public void setReferrerNodeId(String referrerNodeId) {
        fieldValues.put("referrerNodeId", referrerNodeId);
    }

    /**
     * sets the link id
     * @param v the linkId
     */
    public void setLinkId(String linkId) {
        fieldValues.put("linkId", linkId);
    }   // Eigentlich etwas redundant...

    /**
     * sets the link type
     * @param v the link type
     * @see scone.netobjects.Link
     */
    public void setLinkType(int linkType) {
        fieldValues.put("linkType", String.valueOf(linkType));
    }   // Eigentlich etwas redundant...

    /**
     * sets the it took to load this page in browser
     * @param v the loadTime
     */
    public void setLoadTime(long loadTime) {
        fieldValues.put("loadTime", String.valueOf(loadTime));
    }

    /**
     * sets the time the user had this page opened in browser
     * @param v the stayTime
     */
    public void setStayTime(long stayTime) {
        fieldValues.put("stayTime", String.valueOf(stayTime));
    }

    /**
     * returns the user id
     * @return the userId
     */
    public String getUserId() {
        return fieldValues.get("userId");
    }

    /**
     * returns the node id
     * @return the nodeid
     */
    public String getNodeId() {
        return fieldValues.get("nodeId");
    }

    /**
     * returns the time when the page was starting to load
     * @return the time
     */
    public long   getTime() {
        return Long.parseLong(fieldValues.get("time"));
    }

    /**
     * returns the frame name
     * @return the frameName
     */
    public String getFrameName() {
        return fieldValues.get("frameName");
    }

    /**
     * returns the id of this access event
     * @return the accessId
     */
    public String getAccessId() {
        return fieldValues.get("accessId");
    }

    /**
     * returns the id of the parent access event (in frameset)
     * @return the parentAccessId
     */
    public String getParentAccessId() {
        return fieldValues.get("parentAccessId");
    }

    /**
     * returns the bit array action
     * @return the action
     */
    public int    getAction() { return Integer.parseInt(fieldValues.get("action")); }

    /**
     * returns the event string
     * @return the event
     */
    public String getEvent() { return fieldValues.get("event"); }
    
    /**
     * returns the string with the position of the last link
     * @return the linkpos
     */
    public String getLinkPos() { return fieldValues.get("linkPos"); }
    
    /**
     * returns the text of the last link anchor
     * @return the link anchor string
     */
    public String getLinkAnchor() { return fieldValues.get("linkAnchor"); }
    
    /**
     * returns the title of the last link
     * @return the event
     */
    public String getLinkTitle() { return fieldValues.get("linkTitle"); }
    
    /**
     * returns size of window before user entered this page...
     * @return the window size aaaXbbb
     */
    public String getLastWindowSize() { return fieldValues.get("windowSize"); }
    
    /**
     * returns the number of Pages the user jumped back or next
     * @return the stepsInHistory
     */
    public int    getStepsInHistory() {
        return Integer.parseInt(fieldValues.get("stepsInHistory"));
    }

    /**
     * returns the fragment string
     * @return the fragment
     */
    public String getFragment() {
        return fieldValues.get("fragment");
    }

    /**
     * returns the query string
     * @return the query
     */
    public String getQuery() {
        return fieldValues.get("query");
    }

    /**
     * returns the post string
     * @return the POST parameters of this access event
     */
    public String getPost() {
        return fieldValues.get("post");
    }

    /**
     * returns the parent frame node id
     * @return the parentFrameNodeId
     */
    public String getParentFrameNodeId() {
        return fieldValues.get("parentFrameNodeId");
    }

    /**
     * returns the parent frame name
     * @return the parentFrameName
     */
    public String getParentFrameName() {
        return fieldValues.get("parentFrameName");
    }

    /**
     * returns the referrer node id
     * @return the referrerNodeId
     */
    public String getReferrerNodeId() {
        return fieldValues.get("referrerNodeId");
    }

    /**
     * returns the link id
     * @return the linkId
     */
    public String getLinkId() {
        return fieldValues.get("linkId");
    }

    /**
     * returns the load time
     * @return the loadTime
     */
    public int   getLinkType() {
        return Integer.parseInt(fieldValues.get("linkType"));
    }

    /**
     * returns the load time
     * @return the loadTime
     */
    public long   getLoadTime() {
        return Long.parseLong(fieldValues.get("loadTime"));
    }

    /**
     * returns the stay time
     * @return the stayTime
     */
    public long   getStayTime() {
        return Long.parseLong(fieldValues.get("stayTime"));
    }

    /**
     * returns the accessed node
     * @return the accessed node
     */
    public NetNode getNode() {
        return NetNodeCache.getById(fieldValues.get("nodeId"));
    }

    /**
     * returns the node in the parent frame
     * @return the node in the parent frame
     */
    public NetNode getParentFrameNode() {
        return NetNodeCache.getById(fieldValues.get("parentFrameNodeId"));
    }

    /**
     * returns the referrer node
     * @return the referrer node
     */
    public NetNode getReferrerNode() {
        return NetNodeCache.getById(fieldValues.get("referrerNodeId"));
    }

    /**
     * returns the user
     * @return the user
     */
    public User getUser() {
        return UserCache.getById(fieldValues.get("userId"));
    }

    /**
     * store object to DB
     */
    public void store() {
        dbTable.updateDB(this);
    }

    /**
     * Key for Hashtable
     */
    public Object getKey(int keyNo) {
        String userId = fieldValues.get("userId");
        String nodeId = fieldValues.get("nodeId");
        String time = fieldValues.get("time");
        String frameName = fieldValues.get("frameName");

        return AccessCache.createKey(userId, nodeId, time, frameName);
    }


    /**
     * returns if this access event was already displayed.
     * @return if it was already shown
     */
    public boolean getShown() {
        return shown;
    }

    /**
     * @param _shown set if this event was already shown...
     */
    public void setShown(boolean _shown) {
        this.shown = _shown;
    }



}
