package page.example;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.FormData;
import org.wikiwebserver.handler.http.HTTPException;
import org.wikiwebserver.handler.http.HTTPHandler;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;
import org.wikiwebserver.html.TemplatedPage;

import page.config.SiteTemplatedPage;

import page.tools.entity.Browser;
import static org.wikiwebserver.html.HTMLHelper.*;

public class Mobiliser extends SiteTemplatedPage implements HTTPResponder {
    
    private static final int MAX_PAGE_SIZE = 100 * 1024;
    
    public void init(HTTPHandler conn) throws HTTPException {
        this.setPageType(TemplatedPage.PAGE_TYPE_MOBILE);    
        super.init(conn);        
    }

    public void generate() throws HTTPException {
        
        String urlString = null;
        String startUrl = null;
        Browser b = getBrowser();
        if (b != null) {
            startUrl = (String) b.get("mobiliserStartUrl");
            if (startUrl == null) {
                startUrl = "http://www.bbc.co.uk";
            }
        }

        FormData formData = getFormData();
        if (formData != null) {
            startUrl = formData.getFirst("startUrl");            
            
            urlString = formData.getFirst("url");
            String encString = formData.getFirst("enc");
            if (encString != null) {
                if (encString.equals("urlEncoded")) {
                    urlString = WareHouse.formDataDecode(urlString);
                }
            }
        }
        
        if (urlString == null) {
            setTitle("Mobiliser - WikiWebServer.org"); 
            append("<h1>Mobiliser</h1>" +
                    "<h2>Reformats web sites for mobile devices</h2>" +
                    "<p>Strips web pages of complicated formatting and resizes embedded" +
                    " images so that standard pages can be viewed on portable devices " +
                    " using minimal bandwidth.</p>" +
                    "<form><h2>URL to mobilise</h2>" +     
                    textfield("url", startUrl, "size='60'") +
                    "<br/><input type='submit' class='submit' value='Mobilise'></form>" +
                    "<h2>Examples</h2>");
            
            String[] examples = { "www.bbc.co.uk", "www.theregister.co.uk", 
                                  "www.tomshardware.com", "www.wired.com", 
                                  "www.engadget.com" };
            
            String[] links = new String[examples.length];
            for (int i=0; i<examples.length; i++) {
                links[i] = "<a href='" + getUrl() + "?url=http://" + examples[i] + "'>" +
                           examples[i] + "</a>";
            }
            
            append(ul(links));
            
            return;
        }
        
     
        
        
        HttpURLConnection pageConn = null;
        InputStream in = null;
        try {
            URL url = new URL(urlString);  
            pageConn = (HttpURLConnection) url.openConnection();
            
            // The URL can be changed by a redirect, update it
            url = pageConn.getURL();
        
            String contentType = pageConn.getContentType();

            if (contentType != null && !contentType.startsWith("text/")) {
                throw new HTTPException(500, "Unsupported content type: " + contentType);
            }
            
            int contentLength = pageConn.getContentLength();
            // Limit size of page read
            if (contentLength == -1 || contentLength > MAX_PAGE_SIZE) {
                contentLength = MAX_PAGE_SIZE;
            }            
        
            // Read response
            in = pageConn.getInputStream(); 
            byte[] data = WareHouse.streamToByteArray(in, contentLength);
            
            String enc = "iso-8859-1";
            String page = new String(data, enc);
            
            // Quick dirty search for character encoding
            String charTag = "charset=";
            int sidx = page.indexOf(charTag);
            if (sidx > -1) {
                int eidx1 = page.indexOf("\"", sidx);
                int eidx2 = page.indexOf("\'", sidx);
                int eidx3 = page.indexOf(" ", sidx);
                int eidx4 = page.indexOf(">", sidx);
                int eidx = minValid(eidx1, eidx2, eidx3, eidx4);
                enc = page.substring(sidx+charTag.length(), eidx);
                try { page = new String(data, enc);
                } catch (UnsupportedEncodingException ex) {}
            }
            
            
            String serverRoot = url.getProtocol() + "://" + url.getHost();    
            if (url.getPort() != -1 && url.getPort() != 80) {
                serverRoot += ":" + url.getPort();
            }
            
            String pageRoot = url.getPath();
            if (pageRoot == null || pageRoot.length() == 0) {
                pageRoot = "/";
            }
            else if (!pageRoot.endsWith("/")) {
                pageRoot = pageRoot.substring(0, pageRoot.lastIndexOf("/")+1);
            }
            
            MobilePageReformatter formatter = new MobilePageReformatter(serverRoot, pageRoot, getUrl());
            String reformatted = formatter.reformat(page);
            
            setTitle(formatter.getTitle() + " - Reformatted by WikiWebServer.org"); 

            append("<p>Viewing: " + url.toString() + " ");   
            append("<a href='" + getUrl() + "?startUrl=" + url.toString() + "'>change</a></p>");
            append("<h1>" + formatter.getTitle() + "</h1>");
            append(reformatted);
            
            if (b != null) {
                b.put("mobiliserStartUrl", url.toString());
            }

        } 
        catch (HTTPException ex) {
            throw ex;
        } 
        catch (Throwable ex) {
            if (pageConn != null) {
                int code = 500;
                String info = "No error message to proxy";
                try {
                    code = pageConn.getResponseCode();
                    info = pageConn.getResponseMessage();
                } catch (IOException ex2) { }
                
                HTTPException httpe = new HTTPException(code, info);
                httpe.initCause(ex);                
                throw httpe;
            }
        } 
        finally {
            if (in != null) {
                try { in.close(); } catch (IOException ex2) { }
            }
        }
    }   
    
    private static int minValid(int i, int j, int k, int l) {
        return minValid(minValid(i, j), minValid(j, k), minValid(k, l));
    }      
    
    private static int minValid(int i, int j, int k) {
        return minValid(minValid(i, j), minValid(j, k));
    }    
    
    private static int minValid(int a, int b) {
        if (a == -1) return b;
        if (b == -1) return a;
        return (a < b) ? a : b;
    }    
}
