package org.wikiwebserver.handler.http.responder;

import static org.wikiwebserver.html.HTMLHelper.*;

import java.io.IOException;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.HTTPPostReader;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;

public class ExceptionResponder implements HTTPResponder {
    
    public static final int MAX_POST_BYTES_TO_SKIP = 100 * 1024;

	private Throwable exception;
	
	public ExceptionResponder(Throwable throwable) {
		this.exception = throwable;
	}

	public Object respond(HTTPHandler conn) throws IOException {
	    
	    // Try to complete reading posted data
	    if (conn.getRequest() != null) {
    	    Object requestData = conn.getRequest().getData();
    	    if (requestData instanceof HTTPPostReader) {
    	        int bytesToRead = ((HTTPPostReader)requestData).remaining();
    	        if (bytesToRead > 0 && bytesToRead < MAX_POST_BYTES_TO_SKIP) {
    	            ((HTTPPostReader)requestData).skip(bytesToRead);
    	        }
    	        else {
    	            // Don't salvage this connection
    	            conn.getResponse().getHeaders().set("Connection", "close");	
    	            return null;
    	        }
    	    }
	    }

        HTTPException httpEx = null;
        // Wrap standard exceptions
        if (exception instanceof HTTPException) {
            httpEx = (HTTPException) exception;
        } else {
            String msg = "Failed to serve request";
            httpEx = new HTTPException(500, msg, exception);
        }
        
        if (conn.getResponse().getNumBytesWritten() > 0) {
            // We can not send an error if headers sent and length specified
            String contentType = conn.getResponse().getHeaders().getFirst("Content-Type");
            String contentLength = conn.getResponse().getHeaders().getFirst("Content-Length");

            if (contentLength != null || !contentType.contains("text/html")) {
                return null;
            }
            
            // ...unless the content type is html, if so append javascript error
            // NOTE this will not always work if stuck in <,',"
            String message = httpEx.getMessage() + " (" + httpEx.getCode() + ")\\n\\n"
                           + httpEx.getMessage() + "\\n"
                           + WareHouse.formatStackTrace(httpEx.getStackTrace(), false, true);
            
            StringBuilder popup = new StringBuilder();
            popup.append("<script language='JavaScript'>" + LF + "<!--" + LF);
            popup.append("window.alert('" + message + "');" + LF);
            popup.append("-->" + LF + "</script>" + LF);
            
            return popup.toString();
        }
        else {
            conn.getResponse().setCode(httpEx.getCode());
            conn.getResponse().setInfo(httpEx.getMessage());
            conn.getResponse().getHeaders().setAll(httpEx.getHeaders());
            conn.getResponse().setData(httpEx);
            
            if (conn.getHTTPConfig() != null && 
                conn.getHTTPConfig().getHTTPErrorResponder(httpEx) != null) {
                
                return conn.getHTTPConfig().getHTTPErrorResponder(httpEx);
            }
            else {
                return h(1, httpEx.getCode() + ": " + httpEx.getMessage());
            }
        }
    }	  
}

