package org.wikiwebserver.html;

import java.io.IOException;
import java.util.Map;
import java.util.HashMap;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.*;
import org.wikiwebserver.handler.http.interfaces.*;


public abstract class BasicTemplatedPage implements HTTPResponder, CacheableHTTPResponse {
    
    protected abstract void generate() throws HTTPException;      
    
    public void init(HTTPHandler conn) throws HTTPException {
        this.conn = conn;
        this.reader = conn.getInputStream();
        this.request = conn.getRequest();
        this.writer = conn.getOutputStream();
        this.response = conn.getResponse();
        this.response.getHeaders().set("Content-Type", "text/html; charset=utf-8");        
    }    

    public Object respond(HTTPHandler conn) throws IOException {
        
        // Invoke the generate method implemented by the subclass
        generate();

        return getPopulatedTemplate();
    }
    
    public String getAbsolutePath(String resource) {
        if (!resource.startsWith("/") && getResourceRoot() != null) {
            resource = getResourceRoot() + resource;
        }
        return resource;
    }    
    
    public void setResourceRoot(String path) {
        if (!path.endsWith("/")) path += "/";
        this.resourceRoot = path;
    }    
    
    public String getResourceRoot() {
        return this.resourceRoot;
    }

    public void setTemplatePath(String path) {        
        this.templatePath = path;
    }

    public String getServiceAddress() {
        return conn.getServiceAddress();
    }

    public String getUrl() {
        return request.getUrl();
    }
    
    public String getUri() {
        return request.getUri();
    }
    
    public String getQuery() {
        return request.getQuery();
    }    

    public Object getPostedData() {
        return request.getData();
    }
    
    public HTTPHandler getHandler() {
        return conn;
    }    

    public HTTPInputStream getReader() {
        return reader;
    }

    public HTTPRequest getRequest() {
        return request;
    }

    public HTTPOutputStream getWriter() {
        return writer;
    }

    public HTTPResponse getResponse() {
        return response;
    }

    public FormData getFormData() {
        return request.getFormData();
    }

    public Map<String, String> getCookie() {
        return request.getHeaders().getRequestCookies();
    }
    
    public BasicTemplatedPage appendToHead(String s) {
        head.append(s);
        return this;
    }

    public BasicTemplatedPage append(String s) {
        body.append(s);
        return this;
    }    
    
    public BasicTemplatedPage append(TemplatedPage inner) throws HTTPException {
        inner.init(getHandler());
        inner.generate();
        append(inner.getBody());
        return this;
    }     
    
    protected void clearHead() {
        head = new StringBuilder();
    }

    protected String getHead() {
        return head.toString();
    }      
    
    protected void clearBody() {
        body = new StringBuilder();
    }

    protected String getBody() {
        return body.toString();
    }    

    protected void addTemplateModifications(Map<String, String> changes) throws IOException {

        changes.put("<!-- GENERATED_HEAD -->", getHead());
        changes.put("<!-- GENERATED_BODY -->", getBody());
    }


    protected String getPopulatedTemplate() throws IOException {

        // Trim slash
        templatePath = getAbsolutePath(templatePath);
        
        if (templatePath != null && templatePath.startsWith("/")) {
            templatePath = templatePath.substring(1);
        }
        
        String page = null;
        if (templatePath != null) {
            // Read in the file
            page = WareHouse.getResourceAsString(templatePath);
        }
        
        // Basic template in the event there is no template file
        if (page == null) {
            page = "<html><head><!-- GENERATED_HEAD --></head>"
                 + "<body><!-- GENERATED_BODY --></body></html>";
        }

        Map<String, String> changes = new HashMap<String, String>();
        addTemplateModifications(changes);
        
        return WareHouse.performFindReplace(page, changes);  
    }
    
    public String getCacheKey() {
        return cacheKeyBasedOnFormData();
    }

    public long getExpireTime() {
        return System.currentTimeMillis() + DEFAULT_EXPIRE;
    }
    
    public String cacheKeyBasedOnFormData() {
        if (getFormData() == null) return "";
        return WareHouse.getMD5String(getFormData().toString());
    }
    
    public String cacheKeyBasedOnCookieData() {
        if (getRequest().getHeaders().getRequestCookies() == null) return "";
        return WareHouse.getMD5String(getRequest().getHeaders().getRequestCookies().toString());
    }    
    
    public String cacheKeyBasedOnRequestHeaderData() {
        if (getRequest().getHeaders() == null) return "";
        return WareHouse.getMD5String(getRequest().getHeaders().toString());
    }     

    private HTTPHandler conn;
    private HTTPInputStream reader;
    private HTTPOutputStream writer;
    private HTTPRequest request;
    private HTTPResponse response;

    private String resourceRoot;
    private String templatePath;
    
    private StringBuilder head = new StringBuilder(256);
    private StringBuilder body = new StringBuilder(1024);

    private static final long DEFAULT_EXPIRE = 60 * 1000;
      
}

