/*
 * ICESOFT COMMERCIAL SOURCE CODE LICENSE V 1.1
 *
 * The contents of this file are subject to the ICEsoft Commercial Source
 * Code License Agreement V1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of the
 * License at
 * http://www.icesoft.com/license/commercial-source-v1.1.html
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 * License for the specific language governing rights and limitations under
 * the License.
 *
 * Copyright 2009-2015 ICEsoft Technologies Canada, Corp. All Rights Reserved.
 */
package com.icesoft.faces.facelets.component;

import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Logger;

import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.icefaces.impl.event.UIOutputWriter;

import com.icesoft.faces.context.JarResource;
import com.icesoft.faces.context.ResourceRegistryLocator;

public class ComponentConfig implements Serializable{

    private Map<String,String> images = new HashMap<String,String>();
    private Map<String,String> imagesNoContext = new HashMap<String,String>();
    private Map<String,String> css = new HashMap<String,String>();
    private Map<String,String> javascript = new HashMap<String,String>();

    private String basePath;

    public Map<String,String> getImages() {
        return images;
    }

    public void setImageRegistry(Map<String,String> imageRegistry) {
        for (Object o : imageRegistry.keySet()) {
            String key = (String) o;
            String imageName = (String) imageRegistry.get(key);
            images.put(key, registerImage(imageName));
            imagesNoContext.put(key, registerImageWithoutContext(imageName));
        }
    }

    public void setJavascriptAutoLoad(String str) {
        if (str != null) {
            StringTokenizer tokens = new StringTokenizer(str, ",");
            while (tokens.hasMoreTokens()) {
                String js = tokens.nextToken().trim();
                registerJavascriptWithRelativePath(js);
            }
        }
    }

    public void setJavascriptRegistry(Map<String,String> jsRegistry) {
        if (jsRegistry != null) {
            for (Object o : jsRegistry.keySet()) {
                String key = (String) o;
                String jsName = (String) jsRegistry.get(key);
                String path = registerJavascript(jsName);
                javascript.put(key, path);
            }
        }
    }

    public Map<String,String> getImagesNoContext() {
        return imagesNoContext;
    }

    public void setCssRegistry(Map<String,String> cssRegistry) {
        for (Object o : cssRegistry.keySet()) {
            String key = (String) o;
            String cssName = (String) cssRegistry.get(key);
            css.put(key, registerCSS(cssName));
        }
    }

    public Map<String,String> getCss() {
        return css;
    }

    public Map<String,String> getJavascript() {
        return javascript;
    }

    protected String getPathBase() {
        if (basePath == null) {
            basePath = this.getClass().getPackage().getName().replace('.', '/') + "/";
        }
        return basePath;
    }

    protected static Logger log = Logger.getLogger("com.icesoft.faces.facelets.component.componentconfig");

    protected void registerJavascriptWithRelativePath(String path) {

        String fullPath;
        if (path.indexOf("/") < 0)
            fullPath = getPathBase() + path;
        else
            fullPath = path;
        JSResource jsResource = new JSResource(fullPath);
        FacesContext facesContext = FacesContext.getCurrentInstance();

        final String url = ResourceRegistryLocator.locate(facesContext).registerResource(jsResource).getPath();

        UIViewRoot root = facesContext.getViewRoot();
        UIOutput icepushCode = new UIOutputWriter() {
            public void encode(ResponseWriter writer, FacesContext context) throws IOException {
                writer.startElement("script", this);
                writer.writeAttribute("type", "text/javascript", null);
                writer.writeAttribute("src", url, null);
                writer.endElement("script");
            }
        };
        icepushCode.setTransient(true);
        root.addComponentResource(facesContext, icepushCode, "head");
    }

    protected String registerJavascript(String path) {
        String fullPath;
        if (path.indexOf("/") < 0)
            fullPath = getPathBase() + path;
        else
            fullPath = path;
        JSResource jsResource = new JSResource(fullPath);
        return ResourceRegistryLocator.locate(FacesContext.getCurrentInstance()).registerResource(
                jsResource).getPath();
    }

    /**
     * Register an image resource for use in the application.
     *
     * @param name The name of the image (may be in same package as Config class or the full path anywhere in the jar)
     * @return The accessible url path of the registered image
     */
    protected String registerImage(String name) {
        String imagePath;
        if (name.indexOf("/") < 0)
            imagePath = getPathBase() + name;
        else
            imagePath = name;
        ImageResource imageResource = new ImageResource(imagePath);
        return ResourceRegistryLocator.locate(FacesContext.getCurrentInstance()).registerResource(
                imageResource).getPath();
    }

    protected String registerImageWithoutContext(String name) {
        String imagePath;
        if (name.indexOf("/") < 0)
            imagePath = getPathBase() + name;
        else
            imagePath = name;
        ImageResource imageResource = new ImageResource(imagePath);
        return ResourceRegistryLocator.locate(FacesContext.getCurrentInstance()).registerResource(
                imageResource).getPath();
    }

    protected String registerCSS(String name) {
        String cssPath;
        if (name.indexOf("/") < 0)
            cssPath = getPathBase() + name;
        else
            cssPath = name;
        CSSResource resource = new CSSResource(cssPath);
        return ResourceRegistryLocator.locate(FacesContext.getCurrentInstance()).registerResource(
                resource).getPath();
    }

    class ImageResource extends JarResource {

        private String mimeType;

        public ImageResource(String path) {
            super(path);
            if (path.toLowerCase().endsWith(".png"))
                mimeType = "image/png";
            else if (path.toLowerCase().endsWith(".gif"))
                mimeType = "image/gif";
            else if (path.toLowerCase().endsWith(".jpg"))
                mimeType = "image/jpg";
        }

        public void withOptions(Options options) throws IOException {
            options.setMimeType(mimeType);
        }
    }

    class CSSResource extends JarResource {

        public CSSResource(String path) {
            super(path);
        }

        public void withOptions(Options options) throws IOException {
            options.setMimeType("text/css");
        }
    }

    class JSResource extends JarResource {

        public JSResource(String path) {
            super(path);
        }

        public void withOptions(Options options) throws IOException {
            options.setMimeType("text/javascript");
        }
    }

    public String getNextUniqueId() {
        return FacesContext.getCurrentInstance().getViewRoot().createUniqueId();
    }

}
