package page.config;


import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import org.wikiwebserver.util.VelocityEnforcement;
import org.wikiwebserver.util.VelocityExceededException;

import static org.wikiwebserver.html.HTMLHelper.*;

public class ExceptionPage extends SiteTemplatedPage implements HTTPResponder {
    
    private HTTPException exception;
    
    public ExceptionPage(HTTPException exception) {
        this.exception = exception;
    }
    
    public String getCacheKey() {
        // Only redirects should be cached
        int code = exception.getCode();
        if (code == 301 || code == 302 || code == 307) {
            String location = getResponse().getHeaders().getFirst("Location"); 
            return code + location;
        }
        return null;
    }
	
    public void generate() throws HTTPException {
        
        int code = exception.getCode();
        
        // Quick and simple redirection page
        if (code == 301 || code == 302 || code == 307) {
            String location = getResponse().getHeaders().getFirst("Location");
            append(h(1, "Redirection") + 
                   p("The object requested can be found here: ") +
                   p(a(location, WareHouse.escapeHTMLEntities(location))));
            
            return;
        }
        
        
        // Don't return full exception details if there is a surge of requests from an IP
        try {        
            String type = "exception_ips";      
            String ip = getHandler().getSourceAddress();
            int limit = 10;
            long period = 10 * 1000;              
            VelocityEnforcement.enforceVelocity(type, ip, limit, period);
        }         
        catch (VelocityExceededException ex) {

            append(h(1, "Reoccuring Problem") + 
                   p(WareHouse.escapeHTMLEntities(exception.getMessage())));
            
            return;
        }

        
        setTitle(code + " " + exception.getMessage());  
        //getResponse().getHeaders().set("Connection", "close");
        
        append(h(1, "Server error") + LF +
               h(2, "Error code: " + code) + LF +
               h(3, "Information: " + 
               WareHouse.escapeHTMLEntities(exception.getMessage())));

        append(getGoogleAdsenseBlock("pub-7253309958196609", "6048577317", 728, 90));
        
        if (code == 404) {
        	
        	append("<style type='text/css'>" + LF +
					  "#goog-wm { }" + LF +
					  "#goog-wm h3.closest-match { }" + LF +
					  "#goog-wm h3.closest-match a { }" + LF +
					  "#goog-wm h3.other-things { }" + LF +
					  "#goog-wm ul li { }" + LF +
					  "#goog-wm li.search-goog { display: block; }" + LF +
					"</style>");
        	
        	append(javaScript("var GOOG_FIXURL_LANG = 'en';" + LF +
        					  "var GOOG_FIXURL_SITE = '" + getServiceAddress() + "';"));
        	
        	append("<script type='text/javascript' src='http://linkhelp.clients.google.com/tbproxy/lh/wm/fixurl.js'></script>");        	
        }
        
        append("<hr/>" + h(2, "Stack trace:") +
               p("<strong>" + exception.getClass().getName() + ": " + 
               WareHouse.escapeHTMLEntities(exception.getMessage()) + "</strong>") +
               "<div style='margin: 5px 10px 20px 20px;'>" +
               WareHouse.formatStackTrace(exception.getStackTrace(), true, false) +
               "</div>");

        boolean doLinkSource = getBrowser() != null;
        
        int causeCount = 0;
        Throwable cause = exception.getCause();
        while (cause != null && causeCount < 10) {
            append(h(2, "Caused by:") +
                   p("<strong>" + cause.getClass().getName() + ": " + 
                   WareHouse.escapeHTMLEntities(cause.getMessage()) + "</strong>") +
                   "<div style='margin: 5px 10px 20px 20px;'>" +
                   WareHouse.formatStackTrace(cause.getStackTrace(), doLinkSource, false) +
                   "</div>");
            causeCount++;
            cause = cause.getCause();
        }
        
        append("<table><tr><th>Thread ID:</th><th>Request ID:</th><th>Browser ID:</th><th>User ID:</th></tr>");
        
        String threadID = Thread.currentThread().getName();
        String logViewer = WareHouse.getUrlPathForClass(page.tools.management.LogViewer.class);
        String browserInfo = WareHouse.getUrlPathForClass(page.tools.stats.BrowserInfo.class);
        String threadLink = logViewer + "?logName=requests&Thread%20ID=" + threadID;
        append("<tr><td><a href='" + threadLink + "'>"  + threadID + "</a></td>");          
        
        String requestID = getRequest().getRequestID();
        String requestLink = logViewer +  "?logName=requests&Request%20ID=" + requestID;
        append("<td><a href='" + requestLink + "'>"  + requestID + "</a></td>");                     
        
        String browserID = getRequest().getHeaders().getRequestCookies().get("browserID");
        if (browserID != null) {
            String browserLink = browserInfo + "?browserID=" + WareHouse.escapeQuotes(browserID);
            append("<td><a href='" + browserLink + "'>"  + WareHouse.escapeHTMLEntities(browserID) + "</a></td>"); 
        }
        else append("<td>No cookie</td>");
        
        String userID = getRequest().getHeaders().getRequestCookies().get("userID");
        if (userID != null) {
            String userLink = browserInfo + "?userID=" + WareHouse.escapeQuotes(userID);
            append("<td><a href='" + userLink + "'>"  + WareHouse.escapeHTMLEntities(userID) + "</a></td>"); 
        }
        else append("<td>Not registered</td>");
        append("</tr></table>");
    }
}