package hyperscout2;


import java.util.Date;
import java.util.Hashtable;

import scone.netobjects.HtmlNodeCache;
import scone.netobjects.LinkToken;
import scone.netobjects.NetNode;
import scone.netobjects.Server;
import scone.netobjects.ServerCache;
import scone.netobjects.SimpleUri;
import scone.proxy.HtmlTokenEditor;
import scone.robot.NoHtmlNodeException;
import scone.robot.Robot;
import scone.robot.RobotHtmlNode;
import scone.robot.RobotTask;
import scone.robot.RobotUser;
import scone.util.ErrorLog;
import scone.util.tokenstream.HtmlTagToken;
import scone.util.tokenstream.SconePipe;
import scone.util.tokenstream.Token;
import scone.util.tokenstream.TokenInputStream;
import scone.util.tokenstream.TokenOutputStream;


/**
 * Adds onClick-Events to all A and AREA elements.<p>
 * These Events make the little popup-Windows visible.<p>
 * Remove <code>title</code> and <code>alt</code> attributes to avoid popups of browser.
 *
 * @author Harald Weinreich
 * @author Volkert Buchmann
 */

public class LinkEventAdder extends HtmlTokenEditor implements RobotUser {

    private Plugin plugin;
    private Robot robot;
    private RobotTask rt;
    private int maxRobotThreads;
    private boolean showUriInStatusbar = true;

    private Hashtable serverlist = new Hashtable();
    private Hashtable nodelist = new Hashtable();

    public LinkEventAdder(Plugin plugin) {
        this.plugin = plugin;
        robot = Robot.instance();
        // Download how many pages?
        if (plugin.getProperties().get("Start robots") != null) {
            int d = Integer.parseInt(plugin.getProperties().get("Start robots"));

            if ((d < 0) || (d > 1000)) {  // Other numbers are quite stupid...
                throw new NumberFormatException();
            } else {
                maxRobotThreads = d;
            }

        }
        // URL im Statusbar oder nicht?...
        if (plugin.getProperties().get("Show URI in statusbar").equals("true")) { 
            showUriInStatusbar = true;
        } else {
            showUriInStatusbar = false;
        }

    }

    public void handleRequest(SconePipe pipe) {
        try {
            TokenInputStream in = pipe.getTokenInputStream();
            TokenOutputStream out = pipe.getTokenOutputStream();

            LinkToken lt = null;
            HtmlTagToken tag = null;
            Token t = null;
            boolean isLink = false;
            int robotThreads = 0;

            while ((t = in.read()) != null) {
                if ((t instanceof LinkToken)) {
                    lt = (LinkToken) t;
                    isLink = true;

                    String onMouseOver = "hs_activate(event,'"
                            + lt.getLink().getLinkId() + "');";

                    if (!showUriInStatusbar) {
                        onMouseOver = "window.statusbar='';" + onMouseOver;
                    }
                    String onMouseOut = "hs_deactivate();";
                    String onClick = "hs_deactivate();";

                    if (lt.hasParam("onmouseover")) {
                        onMouseOver += lt.getParam("onmouseover");
                        lt.removeParam("onmouseover");
                    }
                    if (lt.hasParam("onmouseout")) {
                        onMouseOut += lt.getParam("onmouseout");
                        lt.removeParam("onmouseout");
                    }
                    if (lt.hasParam("onclick")) {
                        onClick += lt.getParam("onclick");
                        lt.removeParam("onclick");
                    }

                    if (!showUriInStatusbar) {
                        onMouseOver += ";return true;";  // To avoid displaying URL in statusbar.
                    }

                    lt.setParam("onmouseover", onMouseOver, "onMouseOver");
                    lt.setParam("onmouseout", onMouseOut, "onMouseOut");
                    lt.setParam("onclick", onClick, "onClick");

                    // remove title and alt to avoid those popups...
                    if (lt.hasParam("title")) {
                        lt.removeParam("title");
                    }
                    if (lt.hasParam("alt")) {
                        lt.removeParam("alt");
                    }

                    // Robot starten, wenn es noch kein Server-Objekt und es ein externer Link ist.
                    NetNode baseNode = lt.getLink().getFromNode();
                    NetNode toNode = lt.getLink().getToNode();
                    Server server = ServerCache.get(lt.getLink().getToNode().getHost());

                    if (!baseNode.getHost().equals(toNode.getHost())
                            &&             // Other host
                                    toNode.getHost().length() >= 5
                            &&                          // Other DNS-Names are quite useless
                                            serverlist.get(toNode.toHostString())
                                    == null &&                  // not yet started.
                            robotThreads < maxRobotThreads)                                         // max 20 threads!
                    {
                        serverlist.put(toNode.toHostString(), toNode.toHostString());
                        try {
                            rt = new RobotTask(new SimpleUri("http://" + toNode.getHost() + "/"), 0, RobotTask.ALL, this);
                            System.out.println("Robot gestartet: " + toNode.getHost() + "<");
                            rt.setMaxPageSize(15000);      // Just load 15k
                            rt.setMaxDownloadTime(7000);  // Try donwloading this url only for 7 secs.
                            rt.setExpiry(60000);          // After 60 s this task is not interesting any more...
                            rt.setUpdateDate((new Date()).getTime() - 1000L * 60L * 5L); // Re-Download only if older than 5 Minutes.
                            robot.scan(rt);
                            robotThreads++;
                        } catch (Exception ex) {
                            System.err.println("Robot Error:" + ex.toString());
                        }
                    }
                    //
                    if (toNode.getHost().length() >= 5
                            &&                          // Other DNS-Names are quite useless
                                    toNode.getQuery().length() == 0
                            &&                         // Ignore Queries
                                    (HtmlNodeCache.check(toNode) == null
                                    || !toNode.getAccessStatus().equals("200"))
                            &&    // Not yet queried or without success
                                    nodelist.get(toNode.toDocString()) == null
                            &&              // not yet started.
                                    serverlist.get(toNode.toDocString()) == null
                            &&            // Homepages are already fetched above!
                                    robotThreads < maxRobotThreads)                           // maximum no. of threads per page...
                    {
                        nodelist.put(toNode.toDocString(), toNode.toDocString());
                        try {
                            rt = new RobotTask(toNode.getSUri(), 0, RobotTask.ALL, this);
                            System.out.println("Robot gestartet: " + toNode.toDocString());
                            if (toNode.getMimeType().indexOf("text") >= 0
                                    || toNode.getMimeType().length() == 0) {  // Ein text-Dokument! 
                                rt.setMaxPageSize(15000);
                                rt.setMaxDownloadTime(7000);  // Try donwloading this url only for 7 secs.
                                rt.setExpiry(60000);          // After 60 s this task is not interesting any more...
                                rt.setUpdateDate((new Date()).getTime() - 1000L * 60L * 60L * 24L * 7); // Re-Download only if older than 7 Days.
                            } else {
                                rt.setHeadOnly(true);         // Get only the head if it's not HTML
                                rt.setExpiry(60000);          // After 60 s this task is not interesting any more...
                            }
                            robot.scan(rt);
                            robotThreads++;
                        } catch (Exception ex) {
                            System.err.println("Robot Error:" + ex.toString());
                        }
                    }

                }// instanceof LinkToken
                if (t instanceof HtmlTagToken) {
                    tag = (HtmlTagToken) t;
                    if (tag.getTagType() == tag.T_IMG && isLink == true) {
                        tag.removeParam("alt");
                    }
                    if ((tag.getTagType() == tag.T_A
                                    || tag.getTagType() == tag.T_AREA)
                            && tag.isEndTag()) {
                        isLink = false;
                    }
                }// is HtmlTagToken
                out.write(t);
            }// while
        } catch (Exception exc) {
            ErrorLog.log(this, "handleRequest()", "", exc);
        }
    }

    // Bekommt die RobotHTMLNode und dann
    public void robotNewPage(RobotHtmlNode robotHtmlNode, RobotTask robotTask) {
        try {
            System.out.println("Seite geladen: " + robotHtmlNode.getHtmlNode().getTitle());
        } catch (NoHtmlNodeException e) {
            System.out.println("Head geladen: " + robotTask.getStartURI().toString());
        }
    }

    public void robotTaskFinished(RobotTask robotTask) {
        System.out.println("Auftrag: " + robotTask.getStartURI().toString() + " Tiefe: " + robotTask.getDepth() + " abgeschlossen");

        /* System.out.println("Results: ");
         Enumeration downloadedNodes = robotTask.getDownloadedNodes();
         int i=0;
         while(downloadedNodes.hasMoreElements()) {
         RobotHtmlNode robotHtmlNode = (RobotHtmlNode)downloadedNodes.nextElement();
         HtmlNode htmlNode = robotHtmlNode.getHtmlNode();
         System.out.println(htmlNode.getNode().getSUri().toString());
         i++;
         } 
         System.out.print("Anzahl: ");
         System.out.println(i);  */
    }

}
