package page.example;

import java.text.ParseException;
import java.util.Map;

import org.wikiwebserver.core.WareHouse;

import page.tools.xml.WikiParser;


public class MobilePageReformatter extends WikiParser {
    
    private String serverRoot = null;    
    private String pageRoot = null;
    private String proxyClass = null;
    private StringBuilder reformatted = new StringBuilder();
    
    private String title = "No content";
    private boolean insideBody = false;
    private boolean insideLink = false;
    private boolean hideText = false;
    
    private static final String[] NEW_LINE_TAGS = { 
        "td", "tr", "li", "div"
    };
    
    private static final String[] ALLOWED_TAGS = { 
        "h1", "h2", "h3", "h4", "h5", "p", "b", "strong", "em",
        /* "ul", "ol", "li" */
    };
    
    public MobilePageReformatter(String serverRoot, String pageRoot, String proxyClass) {
        this.serverRoot = serverRoot;
        this.pageRoot = pageRoot;
        this.proxyClass = proxyClass;
    }
    
    public String reformat(String page) {
        if (page == null) return null;
        
        try {
            parse(page);
        } catch (ParseException ex) {
            append("<h1>Failed to parse page</h1>");
            append("<p>Parse Exception: " + ex.getMessage());
            append(" at character: " + ex.getErrorOffset() + "</p>");
            
            int clippingStart = ex.getErrorOffset() - 50;
            if (clippingStart < 0) clippingStart = 0;
            int clippingEnd = ex.getErrorOffset() + 50;
            if (clippingEnd > page.length()) clippingEnd = page.length();
            
            String before = page.substring(clippingStart, ex.getErrorOffset());
            String error = String.valueOf(page.charAt(ex.getErrorOffset()));
            String after = page.substring(ex.getErrorOffset()+1, clippingEnd);
            
            append("<p>" + WareHouse.escapeHTMLEntities(before) + 
                   "<b>" + WareHouse.escapeHTMLEntities(error) + "</b>" +
                   WareHouse.escapeHTMLEntities(after) + "</p>");
            
            append(WareHouse.formatStackTrace(ex.getStackTrace(), true, false));
        }
        return reformatted.toString();
    }
    
    public String getTitle() {
        return title;
    }
    
    
    
    
    
    
    

    public void openTag(String tagName, Map<String, String> attributes) {
        
        if (tagName.equals("a")) {
            String href = attributes.get("href");
            href = linkify(href);
            if (href != null) {
                append(" <a href='" + href + "'>");
                insideLink = true;
            }
        }
        
        else if (tagName.equals("img")) {
            String src = attributes.get("src");
            String alt = attributes.get("alt");
            if (alt == null) alt = "Image";
            alt.replace("," , "&apos;");            
            
            int minDim = getMinImageDimension(src, attributes);

            if (minDim < 20 && !insideLink) {
                // Tiny images are usually for layout and positioning
                // Hide them if not part of a link  
                return;
            } 
            
            if (minDim < 40) {
                // Small images flow  
                src = imagify(src, 40);    
                if (src != null) {
                    append("<img src='" + src + "' alt='" + alt + "'/>");
                }
            } else {
                // Larger images are put on separate lines
                src = imagify(src, 160);  
                if (src != null) {
                    newLine();
                    // Link very large, unlinked images
                    if (minDim > 400 && !insideLink) {
                        append("<a href='" + imagify(src, 400) + "'>");
                    }
                    append("<img src='" + src + "' alt='" + alt + "'/>");
                    if (minDim > 400 && !insideLink) {
                        append("</a>");                   
                    }
                    newLine();
                }
            }
        }            
        
        else if (tagName.equals("body")) {
            insideBody = true;
        }             
        
        else if (tagName.equals("title")) {
            title = getTextAfterTag();
            hideText = true;
        }       
        
        else if (tagName.equals("style")) {
            hideText = true;
        } 
        
        else if (tagName.equals("script")) {
            hideText = true;
        }   
        
        else if (tagName.equals("table") || tagName.equals("ul") || tagName.equals("ol")) {
            newLine();
        }          
        
        else {
            for (String tag : ALLOWED_TAGS) {
                if (tagName.equals(tag)) {
                    append("<" + tag + ">");
                    break;
                }
            }
        }           
        
        if (insideBody && !hideText) {
            String text = getTextAfterTag();
            if (text != null) {
                append(text);
            }
        }
    }
    
    public void closeTag(String tagName) {
        
        if (tagName.equals("a") && insideLink) {
            append("</a> ");
        }       
        
        else if (tagName.equals("body")) {
            insideBody = false;
        }         
        
        else if (tagName.equals("style")) {
            hideText = false;
        } 
        
        else if (tagName.equals("script")) {
            hideText = false;
        }         
        
        else {
            for (String tag : NEW_LINE_TAGS) {
                if (tagName.equals(tag)) {
                    newLine();
                    break;
                }
            }            
            
            for (String tag : ALLOWED_TAGS) {
                if (tagName.equals(tag)) {
                    append("</" + tag + ">");
                    break;
                }
            }
        }           
    }
    
    public void append(String text) {
        reformatted.append(text);
    }
    
    public void newLine() {
        // Avoid adding multiple new lines
        if (reformatted.lastIndexOf("<br/>") != reformatted.lastIndexOf("<")) {
            reformatted.append("<br/>");
        }
    }
    
    private int getMinImageDimension(String src, Map<String, String> attributes) {
        int minDim = Integer.MAX_VALUE;
        
        // Retrieve image size from HTML
        String widthString = attributes.get("width");
        String heightString = attributes.get("height");
        if (widthString != null) {
            if (!widthString.contains("%")) {
                widthString = widthString.replace("px", "");
                int width = Integer.parseInt(widthString);
                minDim = width;
            }
        }
        if (heightString != null) {
            if (!heightString.contains("%")) {
                heightString = heightString.replace("px", "");                
                int height = Integer.parseInt(heightString);
                if (height < minDim) minDim = height;
            }
        }    
        
        // If size not found, query image for size
        if (minDim == Integer.MAX_VALUE) {
            minDim = page.image.ImageResizer.getMinDimension(qualifyLink(src));
        }
        
        return minDim;
    }
    
    private String qualifyLink(String url) {
        if (url == null) {
            return null;
        }
        else if (url.toLowerCase().startsWith("javascript:")) {
            return null;
        }
        else if (url.startsWith("/")) {
            return serverRoot + url;
        }
        else if (!url.startsWith("http://") && !url.startsWith("https://")) {
            return serverRoot + pageRoot + url;
        }    
        return url;
    }
    
    private String linkify(String url) {
        String link = qualifyLink(url);
        if (link == null) return null;
        
        return proxyClass + "?url=" + WareHouse.formDataEncode(link) + "&amp;enc=urlEncoded";
    } 
    
    private String imagify(String url, int maxDim) {
        String link = qualifyLink(url);
        if (link == null) return null;
        return WareHouse.getUrlPathForClass(page.image.ImageResizer.class) +
        	   "?path=" + WareHouse.formDataEncode(link) + "&amp;s=" + maxDim;
    }    
}

