package org.wikiwebserver.html;

import java.util.Collection;
import java.util.Map;

import org.wikiwebserver.core.WareHouse;
import org.wikiwebserver.handler.http.interfaces.HTTPResponder;

public class HTMLHelper {
    
    private static final String GOOGLE_AD_CLIENT = "pub-5808326872379244";    
    
    public static enum ContainerType { ID, CLASS };
    
    public static enum TableHeading 
        { NO_HEADING, TOP_HEADING, LEFT_HEADING, TOP_AND_LEFT_HEADING };
       
    private HTMLHelper() {

    }  
    
    public static String applet(String code, 
            String archive, 
            String codebase, 
            int width,
            int height,
            Map<String, String> params) {   
        
        return applet(code, archive, codebase, width, height, params, null);
    }
    
    public static String applet(String code, 
                                String archive, 
                                String codebase, 
                                int width,
                                int height,
                                Map<String, String> params, 
                                String additional) {
        
        StringBuilder bill = new StringBuilder();
        
        bill.append("<applet code='");
        bill.append(code);
        if (archive != null) {
            bill.append("' archive='");
            bill.append(archive);
        }
        if (codebase != null) {
            bill.append("' codebase='");
            bill.append(codebase);            
        }
        bill.append("' height='");
        bill.append(String.valueOf(height));
        bill.append("' width='");
        bill.append(String.valueOf(width));        
        bill.append("'");
        
        if (additional != null) {
            bill.append(" ");
            bill.append(additional);
        }
        bill.append(">");
        
        if (params != null) {
            for (Map.Entry<String, String> param : params.entrySet()) {
                bill.append("<param name='");
                bill.append(param.getKey());
                bill.append("' value='");
                bill.append(param.getValue());
                bill.append("'>");
            }
        }
        
        bill.append("</applet>");
        
        return bill.toString();
    }
    
    public static String meta(String name, String content) {
        return "<meta name='" + name + "' content='" + content + "'>";
    }  
    
    public static String link(String rel, String href, String type) {
        return "<meta rel='" + rel + "' href='" + href + "' type='" + type + "'>";
    }  
    
    public static String comment(String comment) {
        return "<!-- " + comment + " -->";
    }
    
    public static String span(String id) {
        return span(id, null, "");
    }

    public static String span(String id, String content) {
        return span(id, null, content);
    }
    
    public static String span(String id, String additional, String content) {
        return span(ContainerType.ID, id, additional, content);
    } 
    
    public static String span(ContainerType type, String idOrClass, String additional, String content) {
        if (type == ContainerType.ID) {
            return container("span", idOrClass, null, additional, content);
        } else {
            return container("span", null, idOrClass, additional, content);
        }
    }

    public static String div(String id) {
        return div(id, null, "");
    }

    public static String div(String id, String content) {
        return div(id, null, content);
    }
    
    public static String div(String id, String additional, String content) {
        return div(ContainerType.ID, id, additional, content);
    }  
    
    public static String div(ContainerType type, String idOrClass) {
        return div(type, idOrClass, null, null);
    }     
    
    public static String div(ContainerType type, String idOrClass, String content) {
        return div(type, idOrClass, null, content);
    }      
    
    public static String div(ContainerType type, String idOrClass, String additional, String content) {
        if (type == ContainerType.ID) {
            return container("div", idOrClass, null, additional, content);
        } else {
            return container("div", null, idOrClass, additional, content);
        }
    }     
    
    public static String cleardiv() {
        return container("div", null, "clear", null, null);
    }      

    private static String container(String type, String id, String cls, String additional, String content) {
        StringBuilder builder = new StringBuilder();

        builder.append("<" + type);
        if (id != null) builder.append(" id='" + id + "'");
        if (cls != null) builder.append(" class='" + cls + "'");
        if (additional != null) builder.append(" " + additional);
        builder.append(">");
        if (content != null) builder.append(content);
        builder.append("</" + type + ">");

        return builder.toString();
    }

    public static String include(String webPath) {
        return include(webPath, "<pre>FAILED TO INCLUDE " + webPath + "</pre>");
    }

    public static String include(String webPath, String errorIfFail) {
        // Trim slash
        webPath = webPath.substring(1);
        try {
            return WareHouse.getResourceAsString(webPath);
        } catch (Exception e) {
            return errorIfFail;
        }
    }
    

    public static String javaScript(String javaScript) {
        return embedSpecial("script", "text/javascript", javaScript);
    }

    public static String updateHTMLScript(String id, String content) {
        content = WareHouse.escapeStringForJavaScript(content);
        return "document.getElementById('" + id + "').innerHTML='" + content
                + "';" + LF;
    }
    
    public static String updateValueScript(String id, String oldValue, String newValue) {
        oldValue = WareHouse.escapeStringForJavaScript(oldValue);
        newValue = WareHouse.escapeStringForJavaScript(newValue);
        
        return "setObjectValue('" + id + "', '" + oldValue + "', '" + newValue + "');" + LF;
    }    

    public static String updateValueScript(String id, String value) {
        value = WareHouse.escapeStringForJavaScript(value);
        return "document.getElementById('" + id + "').value='" + value + "';" + LF;
    }

    public static String updateSrcScript(String id, String url) {
        return "document.getElementById('" + id + "').src='" + url + "';" + LF;
    }
    
    public static String updateClassNameScript(String id, String newClassName) {
        return "document.getElementById('" + id + "').className='" + newClassName + "';" + LF;
    }

    public static String image(String src, String alt) {
        return image(src, alt, null);
    }

    public static String image(String src, String alt, String additional) {

        StringBuilder img = new StringBuilder();
        img.append("<img src='" + src + "' " + "alt='" + alt + "'");
        if (additional != null) {
            img.append(" " + additional);
        }
        img.append(">");
        return img.toString();
    }

    public static String thumbnail(String src, String alt, int maxDim) {
        return thumbnail(src, alt, maxDim, null);
    }

    public static String thumbnail(String src, String alt, int maxDim, String additional) {
        if (!src.contains("?")) {
            src = WareHouse.getUrlPathForClass(page.image.ImageResizer.class)
                + "?path=" + WareHouse.formDataEncode(src) + "&amp;s=" + maxDim;
        }
        return image(src, alt, "class='thumbnail'");
    }
    

    
    public static String ajaxLoadingBar() {
        return div((String)null, image("/templates/default/images/ajax-loader-bar.gif", "WikiWebServer busy"));
    }   
    
    public static String a(Class<? extends HTTPResponder> clazz, String content) {
        return a(WareHouse.getUrlPathForClass(clazz), content, null);
    }    

    public static String a(String href) {
        return a(href, href, null);
    }

    public static String a(String href, String content) {
        return a(href, content, null);
    }

    public static String a(String href, String content, String additional) {
        StringBuilder link = new StringBuilder();
        link.append("<a");
        if (href != null) {
        	link.append(" href='" + WareHouse.escapeHTMLEntities(href) + "'");
        }
        if (additional != null) link.append(" " + additional);
        link.append(">");
        if (content != null) link.append(content);
        link.append("</a>");
        return link.toString();
    }
    
    public static String p(String paragraph) {
        return "<p>" + paragraph + "</p>";
    }
    
    public static String p(String paragraph, String additional) {
        return "<p " + additional + ">" + paragraph + "</p>";
    }    
    
    public static String strong(String text) {
        return "<strong>" + text + "</strong>";
    }    
    
    public static String label(String name, String content) {
        return "<label name='" + name + "'>" + content + "</label>";
    }     
    
    public static String strong(String text, String additional) {
        return "<strong " + additional + ">" + text + "</strong>";
    }      
    
    public static String br() {
        return "<br>";
    }

    public static String h(int level, String title) {
        return h(level, null, title);
    }
    
    public static String h(int level, String special, String title) {
        StringBuilder heading = new StringBuilder();
        heading.append("<h" + level);
        if (special != null) heading.append(" " + special);
        heading.append(">" + title + "</h" + level + ">");
        return heading.toString();
    }    

    public static String ul(String[] items) {
        return l("ul", items);
    }

    public static String ol(String[] items) {
        return l("ol", items);
    }
    
    public static String table(String[][] data) {
        return table(data, TableHeading.NO_HEADING);
    }    
    
    public static String table(String[][] data, TableHeading headingType) {
        return table(data, headingType, null);
    }   
    
    public static String table(String[][] data, TableHeading headingType, String additional) {
        
        StringBuilder table = new StringBuilder();
        table.append("<table");
        if (additional != null) table.append(" " + additional);
        table.append(">");
        for (int r=0; r<data.length; r++) {

            table.append("<tr>");
            for (int c=0; c<data[r].length; c++) {
                if (data[r][c] == null) {
                    table.append("<td></td>");
                }                 
                else if (headingType == TableHeading.TOP_HEADING && r == 0) {
                    table.append("<th>" + data[r][c] + "</th>");
                }    
                else if (headingType == TableHeading.LEFT_HEADING && c == 0) {
                    table.append("<th>" + data[r][c] + "</th>");
                } 
                else if (headingType == TableHeading.TOP_AND_LEFT_HEADING && (c==0 || r==0)) {
                    table.append("<th>" + data[r][c] + "</th>");
                }                  
                else table.append("<td>" + data[r][c] + "</td>");
            }
            table.append("</tr>");
        }
        table.append("</table>");
        
        return table.toString();
    }      
    

    private static String l(String tag, String[] items) {
        StringBuilder l = new StringBuilder();
        l.append("<" + tag + ">");
        for (String item : items) {
            l.append("<li>" + item + "</li>");
        }
        l.append("</" + tag + ">");
        return l.toString();
    }    
    
    public static String textarea(String name, String content) {
        return textarea(name, content, null);
    }

    public static String textarea(String name, String content, String special) {
        StringBuilder builder = new StringBuilder();

        builder.append("<textarea id='" + name + "' name='" + name + "' ");
        if (special != null)
            builder.append(special);
        builder.append(">");
        if (content != null)
            builder.append(WareHouse.escapeHTMLEntities(content));
        builder.append("</textarea>");

        return builder.toString();
    }

    public static String textfield(String name) {
        return input(name, name, null, null, "text");
    }

    public static String textfield(String name, String value) {
        return input(name, name, value, null, "text");
    }

    public static String textfield(String name, String value, String special) {
        return input(name, name, value, special, "text");
    }

    public static String passwordfield(String name) {
        return input(name, name, null, null, "password");
    }

    public static String passwordfield(String name, String value) {
        return input(name, name, value, null, "password");
    }

    public static String passwordfield(String name, String value, String special) {
        return input(name, name, value, special, "password");
    }
    
    public static String hiddenfield(String name, String value) {
        return input(name, value, "hidden");
    }    
    
    public static String checkbox(String name, String value) {
        return input(name, name, value, null, "checkbox");
    }    
    
    public static String checkbox(String name, String value, String special) {
        return input(name, name, value, special, "checkbox");
    }      
    
    public static String input(String name, String value, String type) {
        return input(name, null, value, null, type);
    }

    public static String input(String name, String id, String value, String special, String type) {
        StringBuilder builder = new StringBuilder();

        builder.append("<input type='" + type + "' class='" + type + "'");
        if (id != null) builder.append(" id='" + id + "'");
        builder.append(" name='" + name + "' ");
        if (value != null) builder.append(" value='" + WareHouse.escapeQuotes(value) + "'");
        if (special != null) builder.append(" " + special);
        builder.append(">");

        return builder.toString();
    }    
    
    public static String select(String name, Object[] values, Object selected) {   
        return select(name, values, selected, null);
    }
    
    public static String select(String name, Collection<?> values, Object selected) {   
        Object[] array = null;
        if (values != null) {
            array = values.toArray(new Object[values.size()]);
        }
        return select(name, array, selected, null);
    }    
    
    public static String select(String name, Collection<?> values, 
                                Object selected, String additional) {
        Object[] array = null;
        if (values != null) {
            array = values.toArray(new Object[values.size()]);
        }
        return select(name, array, selected, additional);
    }     
    
    public static String select(String name, Object[] values, 
                                Object selected, String additional) {

        StringBuilder options = new StringBuilder();
        
        options.append("<select name='" + name + "'");
        if (additional != null) {
            options.append(" " + additional);
        }
        options.append(">");
        
        for (Object value : values) {
            options.append("<option value='" + WareHouse.escapeQuotes(value.toString()) + "'");
            if (value.equals(selected)) options.append(" selected='true'");
            options.append(">");
            options.append(WareHouse.escapeHTMLEntities(value.toString()));
            options.append("</option>");
        } 
        options.append("</select>");
        
        return options.toString();
    }     

    public static String submitbutton(String name, String value) {
        return input(name, name, value, null, "submit");
    }

    public static String submitbutton(String name, String value, String special) {
        return input(name, name, value, special, "submit");
    }

    public static String form(String content, String action) {

        StringBuilder form = new StringBuilder();
        form.append("<form method='post'");
        if (action != null) form.append(" action='" + action + "'");
        form.append(">");
        form.append(content);
        form.append("</form>");
        
        return form.toString();
    }

    public static String codeBox(String code) {
        code = code.replace("&", "&amp;");
        code = code.replace("\"", "&quot;");
        code = code.replace("<", "&lt;");
        code = code.replace(">", "&gt;");
        code = code.replace(" ", "&nbsp;");
        code = code.replace("\n", "<br>");
        return "<code>" + code + "</code>";
    }
    
    public static String sanitize(String dirty) {
        
        if (dirty != null) {
            // Strip nasties
            dirty = dirty.replace("'", "");
            dirty = dirty.replace("\"", "");
            dirty = dirty.replace("<", "");
            dirty = dirty.replace(">", "");
            dirty = dirty.replace("&", "");
        }   
        
        return dirty;
    }
 
    private static String embedSpecial(String tag, String type, String content) {
        if (content != null && content.length() > 0) {
            return "<" + tag + " type='" + type + "'>" + LF + "<!--" + LF
                    + content + LF + "-->" + LF + "</" + tag + ">" + LF;
        }
        return content;
    }

    private static String embedSpecial(String tag, String type, String url, String error) {
        String content = include(url, "");
        if (content == null || content.length() == 0) {
            return error;
        }
        return embedSpecial(tag, type, content);
    }

    public static String incorporateCSS(String url, boolean embed) {
        if (embed) {
            return embedSpecial("style", "text/css", url, "");
        } else {
            return "<link rel='stylesheet' type='text/css' href='" + url + "'>"
                    + LF;
        }
    }

    public static String incorporateJavaScript(String url, boolean embed) {
        if (embed) {
            return embedSpecial("script", "text/javascript", url, "");
        } else {
            return "<script type='text/javascript' src='" + url + "'></script>"
                    + LF;
        }
    }
    
    public static String getGoogleAdsenseBlock(String adSlot, int width, int height) {
        return getGoogleAdsenseBlock(GOOGLE_AD_CLIENT, adSlot, width, height);
    }
    
    public static String getGoogleAdsenseBlock(String client, String adSlot, int width, int height) {
        
        String setup = "google_ad_client = \"" + client + "\";\n" +
                       "google_ad_slot = \"" + adSlot + "\";\n" +
                       "google_ad_width = " + width + ";\n"  + 
                       "google_ad_height = " + height + ";\n";
        
        String url = "http://pagead2.googlesyndication.com/pagead/show_ads.js";
        
        String style = "padding: 5px 0 0 0; ";
        if (width < 700) {
            style += "margin: 10px 5px 0 5px";
        } else {
            style += "margin: 5px 1px 0 1px";
        }
        return div(ContainerType.CLASS, "adsense", "style='" + style + "'", 
                javaScript(setup) + incorporateJavaScript(url, false));          
    } 

    public static final String LF = "\r\n";
}

