/* 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.felix.ipojo.webconsole;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.HandlerFactory;
import org.apache.felix.ipojo.annotations.Component;
import org.apache.felix.ipojo.annotations.Instantiate;
import org.apache.felix.ipojo.annotations.Provides;
import org.apache.felix.ipojo.annotations.Requires;
import org.apache.felix.ipojo.annotations.ServiceProperty;
import org.apache.felix.ipojo.architecture.Architecture;
import org.apache.felix.ipojo.architecture.HandlerDescription;
import org.apache.felix.ipojo.architecture.InstanceDescription;
import org.apache.felix.ipojo.architecture.PropertyDescription;
import org.apache.felix.ipojo.handlers.dependency.DependencyDescription;
import org.apache.felix.ipojo.handlers.dependency.DependencyHandlerDescription;
import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceDescription;
import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceHandlerDescription;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;

/**
 * iPOJO Web Console plugin.
 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
 */
@SuppressWarnings("serial")
@Component(immediate=true)
@Provides
@Instantiate
public class IPOJOPlugin extends AbstractWebConsolePlugin {
    
    /**
     * Used CSS files.
     */
    private static final String CSS[] = { "/res/ui/bundles.css" , "/iPOJO/res/ui/ipojo.css" };

    /**
     * Template : Instance list.
     */
    private final String INSTANCES;
    
    /**
     * Template : Factory list.
     */
    private final String FACTORIES;
    
    /**
     * Template : Handler list. 
     */
    private final String HANDLERS;
    
    /**
     * Template : Factory details. 
     */
    private final String FACTORY_DETAILS;
    
    /**
     * Template : Instance details. 
     */
    private final String INSTANCE_DETAILS;

    /**
     * Label used by the web console.
     */
    @ServiceProperty(name = "felix.webconsole.label")
    private String m_label = "iPOJO";

    /**
     * Title used by the web console.
     */
    @ServiceProperty(name = "felix.webconsole.title")
    private String m_title = "iPOJO"; 
    
    /**
     * CSS files used by the plugin.
     */
    @ServiceProperty(name= "felix.webconsole.css")
    protected String[] m_css = CSS;

    /**
     * List of available Architecture service.
     */
    @Requires(optional = true, specification = "org.apache.felix.ipojo.architecture.Architecture")
    private List<Architecture> m_archs;

    /**
     * List of available Factories.
     */
    @Requires(optional = true, specification = "org.apache.felix.ipojo.Factory")
    private List<Factory> m_factories;

    /**
     * List of available Handler Factories.
     */
    @Requires(optional = true, specification = "org.apache.felix.ipojo.HandlerFactory")
    private List<HandlerFactory> m_handlers;
    
    /**
     * Instantiates the plugin.
     * This method loads all template files.
     */
    public IPOJOPlugin() {
        INSTANCES = readTemplate("/res/instances.html" );
        FACTORIES = readTemplate("/res/factories.html" );
        HANDLERS = readTemplate("/res/handlers.html" );
        FACTORY_DETAILS = readTemplate("/res/factory.html" );
        INSTANCE_DETAILS = readTemplate("/res/instance.html" );
    }
    
    /**
     * Helper method loading a template file.
     * @param templateFile the template file name
     * @return the template
     */
    private final String readTemplate(final String templateFile) {
        InputStream templateStream = getClass().getResourceAsStream(
                templateFile);
        if (templateStream != null) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] data = new byte[1024];
            try {
                int len = 0;
                while ((len = templateStream.read(data)) > 0) {
                    baos.write(data, 0, len);
                }
                return baos.toString("UTF-8");
            } catch (IOException e) {
                // don't use new Exception(message, cause) because cause is 1.4+
                throw new RuntimeException("readTemplateFile: Error loading "
                        + templateFile + ": " + e);
            } finally {
                try {
                    templateStream.close();
                } catch (IOException e) {
                    /* ignore */
                }

            }
        }

        // template file does not exist, return an empty string
        log("readTemplateFile: File '" + templateFile
                + "' not found through class " + this.getClass());
        return "";
    }

    /**
     * This methods is called by the web console when the plugin is required.
     * This methods writes the corresponding page (loads template and set variables).
     * @param request the request
     * @param response the response
     * @throws ServletException something bad happened
     * @throws IOException something bad happened
     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(
     *  javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void renderContent(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // get request info from request attribute
        final RequestInfo reqInfo = new RequestInfo(request);
        // prepare variables
        DefaultVariableResolver vars = ( ( DefaultVariableResolver ) WebConsoleUtil.getVariableResolver( request ) );
                
        if (reqInfo.instances) { // Instance
            if (reqInfo.name == null) { // All
                response.getWriter().print( INSTANCES );
            } else { // Specific
                vars.put("name", reqInfo.name); // Inject the name variable.
                response.getWriter().print( INSTANCE_DETAILS );
            }
        } else if (reqInfo.factories) { // Factory
            if (reqInfo.name == null) { // All
                response.getWriter().print( FACTORIES );
            } else { // Specific
                vars.put("name", reqInfo.name); // Inject the name variable.
                response.getWriter().print( FACTORY_DETAILS );
            }
        } else if (reqInfo.handlers) { // Handlers
            response.getWriter().print( HANDLERS );
            // No detailed view for handlers.
        } else {
            // Default
            response.getWriter().print( INSTANCES );
        }
    }
    
    /**
     * Writes the JSON object containing the info for all instances.
     * @param pw the writer where the json object is printed.
     * @throws IOException the JSON object cannot be written
     */
    private void getAllInstances(PrintWriter pw) throws IOException {
        try {
            JSONObject resp = new JSONObject();
            // Statline:
            resp.put("count", m_archs.size());
            resp.put("valid_count", StateUtils.getValidInstancesCount(m_archs));
            resp.put("invalid_count", StateUtils.getInvalidInstancesCount(m_archs));
            // End statline
            
            JSONArray instances = new JSONArray();
            for (Architecture arch : m_archs) {
                JSONObject instance = new JSONObject();
                instance.put("name", arch.getInstanceDescription().getName());
                instance.put("factory", arch.getInstanceDescription().getComponentDescription().getName());
                instance.put("state", StateUtils.getInstanceState(arch.getInstanceDescription().getState()));
                instances.put(instance);
            }
            resp.put("data", instances);
            
            pw.print(resp.toString());
        } catch (JSONException e) {
            // Propagate the exception.
            throw new IOException(e.toString());
        }
    }
    
    /**
     * Writes the JSON object containing the info for all factories.
     * @param pw the writer when the json object is printed
     * @throws IOException the JSON object cannot be written
     */
    private void getAllFactories(PrintWriter pw) throws IOException {
        try {
            JSONObject resp = new JSONObject();
            // Statline:
            resp.put("count", m_factories.size());
            resp.put("valid_count", StateUtils.getValidFactoriesCount(m_factories));
            resp.put("invalid_count", StateUtils.getInvalidFactoriesCount(m_factories));
            // End statline

            JSONArray factories = new JSONArray();
            for (Factory factory : m_factories) {
                String version = factory.getVersion();
                String name = factory.getName();
                
                String state = StateUtils.getFactoryState(factory.getState());
                String bundle = factory.getBundleContext().getBundle().getSymbolicName()
                    + " (" + factory.getBundleContext().getBundle().getBundleId() + ")";
                JSONObject fact = new JSONObject();
                fact.put("name", name);
                if (version != null) {
                    fact.put("version", version);
                }
                fact.put("bundle", bundle);
                fact.put("state", state);
                factories.put(fact);
            }
            resp.put("data", factories);
            
            pw.print(resp.toString());
        } catch (JSONException e) {
            // Propagate the exception.
            throw new IOException(e.toString());
        }
    }
    
    /**
     * Writes the JSON object containing the info for all handlers.
     * @param pw the writer when the json object is printed
     * @throws IOException the JSON object cannot be written
     */
    private void getAllHandlers(PrintWriter pw) throws IOException {
        try {
            JSONObject resp = new JSONObject();

            // Statline:
            resp.put("count", m_handlers.size());
            resp.put("valid_count", StateUtils.getValidHandlersCount(m_handlers));
            resp.put("invalid_count", StateUtils.getInvalidHandlersCount(m_handlers));
            // End statline
            
            JSONArray factories = new JSONArray();
            for (HandlerFactory factory : m_handlers) {
                String version = factory.getVersion();
                String name = factory.getHandlerName();
                
                String state = StateUtils.getFactoryState(factory.getState());
                String bundle = factory.getBundleContext().getBundle().getSymbolicName()
                    + " (" + factory.getBundleContext().getBundle().getBundleId() + ")";
                JSONObject fact = new JSONObject();
                fact.put("name", name);
                if (version != null) {
                    fact.put("version", version);
                }
                fact.put("bundle", bundle);
                fact.put("state", state);
                fact.put("type", factory.getType());
                if (! factory.getMissingHandlers().isEmpty()) {
                    fact.put("missing", factory.getMissingHandlers().toString());
                }
                factories.put(fact);
            }
            resp.put("data", factories);
            
            pw.print(resp.toString());
        } catch (JSONException e) {
            // Propagate the exception.
            throw new IOException(e.toString());
        }
    }
    
    /**
     * Writes the JSON object containing details about a specific factory.
     * @param pw the writer
     * @param name the factory name
     * @throws IOException if the json object cannot be written.
     */
    private void getFactoryDetail(PrintWriter pw, String name) throws IOException{
        // Find the factory
        Factory factory = null;
        for (Factory fact : m_factories) {
            if (fact.getName().equals(name)) {
                factory = fact;
            }
        }
        
        if (factory == null) {
            // This will be used a error message (cannot be interpreted as json)
            pw.println("The factory " + name + " does not exist or is private");
            return;
        }
        
        try {
            JSONObject resp = new JSONObject();
            
            // Statline.
            resp.put("count", m_factories.size());
            resp.put("valid_count", StateUtils.getValidFactoriesCount(m_factories));
            resp.put("invalid_count", StateUtils.getInvalidFactoriesCount(m_factories));
            // End of the statline
            
            // Factory object
            JSONObject data = new JSONObject();
            data.put("name", factory.getName());
            data.put("state", StateUtils.getFactoryState(factory.getState()));
            
            String bundle = factory.getBundleContext().getBundle().getSymbolicName()
            + " (" + factory.getBundleContext().getBundle().getBundleId() + ")";
            data.put("bundle", bundle);
            
            // Provided service specifications
            if (factory.getComponentDescription().getprovidedServiceSpecification().length != 0) {
                JSONArray services = new JSONArray
                    (Arrays.asList(factory.getComponentDescription().getprovidedServiceSpecification()));
                data.put("services", services);
            }
            
            // Properties
            PropertyDescription[] props = factory.getComponentDescription().getProperties();
            if (props != null  && props.length != 0) {
                JSONArray properties = new JSONArray();
                for (int i = 0; i < props.length; i++) {
                    JSONObject prop = new JSONObject();
                    prop.put("name", props[i].getName());
                    prop.put("type", props[i].getType());
                    prop.put("mandatory", props[i].isMandatory());
                    prop.put("immutable", props[i].isImmutable());
                    if (props[i].getValue() != null) {
                        prop.put("value", props[i].getValue());
                    }
                    properties.put(prop);
                }
                data.put("properties", properties);
            }
            
            if (! factory.getRequiredHandlers().isEmpty()) {
                JSONArray req = new JSONArray
                    (factory.getRequiredHandlers());
                data.put("requiredHandlers", req);
            }
            
            if (! factory.getMissingHandlers().isEmpty()) {
                JSONArray req = new JSONArray
                    (factory.getMissingHandlers());
                data.put("missingHandlers", req);
            }
            
            List<?> instances = StateUtils.getInstanceList(m_archs, name);
            if (! instances.isEmpty()) {
                JSONArray req = new JSONArray(instances);
                data.put("instances", req);
            }
            
            data.put("architecture", factory.getDescription().toString());
            resp.put("data", data);
            
            pw.print(resp.toString());
        } catch (JSONException e) {
            // Propagate the exception.
            throw new IOException(e.toString());
        }
        
    }
    
    /**
     * Writes the JSON object containing details about a specific instance.
     * @param pw the writer
     * @param name the instance name
     * @throws IOException if the json object cannot be written.
     */
    private void getInstanceDetail(PrintWriter pw, String name) throws IOException {
        // Find the factory
        InstanceDescription instance = null;
        for (Architecture arch : m_archs) {
            if (arch.getInstanceDescription().getName().equals(name)) {
                instance = arch.getInstanceDescription();
            }
        }
        
        if (instance == null) {
            // This will be used a error message (cannot be interpreted as json)
            pw.println("The instance " + name + " does not exist or " +
            		"does not exposed its architecture");
            return;
        }
        
        try {
            JSONObject resp = new JSONObject();
            resp.put("count", m_factories.size());
            resp.put("valid_count", StateUtils.getValidFactoriesCount(m_factories));
            resp.put("invalid_count", StateUtils.getInvalidFactoriesCount(m_factories));
            
            // instance object
            JSONObject data = new JSONObject();
            data.put("name", instance.getName());
            data.put("state", StateUtils.getInstanceState(instance.getState()));
            data.put("factory", instance.getComponentDescription().getName());
            
            JSONArray services = getProvidedServiceDetail(instance.getHandlerDescription("org.apache.felix.ipojo:provides"));
            if (services != null) {
                data.put("services", services);
            }
            
            JSONArray reqs = getRequiredServiceDetail(instance.getHandlerDescription("org.apache.felix.ipojo:requires"));
            if (reqs != null) {
                data.put("req", reqs);
            }
            
            data.put("architecture", instance.getDescription().toString());
            resp.put("data", data);
            
            pw.print(resp.toString());
        } catch (JSONException e) {
            // Propagate the exception.
            throw new IOException(e.toString());
        }
        
    }
    
    /**
     * Endpoint dealing with JSON requests.
     * @param request the request
     * @param response the response
     * @throws ServletException if an error occurred
     * @throws IOException if an error occurred
     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#doGet
     *  (javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
     */
    @Override
    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        final RequestInfo reqInfo = new RequestInfo(request);
        
        if (reqInfo.extension.equals("json")) {
            response.setContentType("application/json");
            if (reqInfo.instances) {
                if (reqInfo.name == null) {
                    this.getAllInstances(response.getWriter());
                    return;
                } else {
                    this.getInstanceDetail(response.getWriter(), reqInfo.name);
                    return;
                }
            }

            if (reqInfo.factories) {
                if (reqInfo.name == null) {
                    this.getAllFactories(response.getWriter());
                    return;
                } else {
                    this.getFactoryDetail(response.getWriter(), reqInfo.name);
                    return;
                }
            }

            if (reqInfo.handlers) {
                this.getAllHandlers(response.getWriter());
            }
            // nothing more to do
            return;
        }
        // Otherwise, delegate to super.
        super.doGet(request, response);
    }
    
    /**
     * Allows loading the 'ui' folder as web resource.
     * @param path the resource path
     * @return the internal resource url.
     */
    public URL getResource(String path) {
        if (path.contains("/res/ui/")) {
            return this.getClass().getResource(
                    path.substring(m_label.length() + 1));
        }
        return null;
    }
    
    /**
     * Creates the JSON Array describing the provided services.
     * @param hd the provided service handler
     * @return the JSON Array or null if no provided service
     * @throws JSONException if the array cannot be created.
     */
    private JSONArray getProvidedServiceDetail(HandlerDescription hd) throws JSONException {
        if (hd == null) {
            return null;
        }

        JSONArray array = new JSONArray();
        ProvidedServiceHandlerDescription desc = (ProvidedServiceHandlerDescription) hd;

        for (ProvidedServiceDescription ps : desc.getProvidedServices()) {
            JSONObject svc = new JSONObject();
            String spec = Arrays.toString(ps.getServiceSpecifications());
            if (spec.startsWith("[")) {
                spec = spec.substring(1, spec.length() - 1);
            }
            svc.put("specification", spec);
            svc.put("state", StateUtils.getProvidedServiceState(ps.getState()));
            
            if (ps.getServiceReference() != null) {
                svc.put("id", (Long) ps.getServiceReference().getProperty(Constants.SERVICE_ID));
            }
            
            if (ps.getProperties() != null  &&!  ps.getProperties().isEmpty()) {
                svc.put("properties", getServiceProperties(ps.getProperties()));
            }

            array.put(svc);
        }
        
        return array;
    }
    
    /**
     * Builds the JSON Array containing object representing the given properties
     * (name / value pair).
     * @param properties the properties
     * @return the JSON Array
     * @throws JSONException if the array cannot be created correctly
     */
    private JSONArray getServiceProperties(Properties properties) throws JSONException {
        JSONArray array = new JSONArray();
        Enumeration<Object> e = properties.keys();
        while (e.hasMoreElements()) {
            String key = (String) e.nextElement();
            Object value = properties.get(key);
            JSONObject prop = new JSONObject();
            prop.put("name", key);
            if (value != null  && value.getClass().isArray()) {
                // TODO Test with primitive types
                prop.put("value", Arrays.toString((Object[]) value));
            } else if (value != null) {
                prop.put("value", value.toString());
            } else {
                prop.put("value", "no value");
            }
            array.put(prop);
        }
        return array;
    }
    
    /**
     * Builds the JSON Array representing the required services.
     * @param hd the dependency handler
     * @return the array containing JSON object representing service
     * dependencies, or null if there is no service dependency.
     * @throws JSONException if the JSON array cannot be created.
     */
    private JSONArray getRequiredServiceDetail(
            HandlerDescription hd) throws JSONException {
        if (hd == null) {
            return null;
        }
        JSONArray array = new JSONArray();
        DependencyHandlerDescription desc = (DependencyHandlerDescription) hd;
        for (DependencyDescription dep : desc.getDependencies()) {
            JSONObject req = new JSONObject();
            req.put("specification",dep.getSpecification());
            req.put("id", dep.getId());
            req.put("state", StateUtils.getDependencyState(dep.getState()));
            req.put("policy", StateUtils.getDependencyBindingPolicy(dep.getPolicy()));
            req.put("optional", dep.isOptional());
            req.put("aggregate", dep.isMultiple());
            if (dep.getFilter() != null) {
                req.put("filter", dep.getFilter());
            }
            if (dep.getServiceReferences() != null  && dep.getServiceReferences().size() != 0) {
                req.put("matching",  getServiceReferenceList(dep.getServiceReferences()));
            }
            
            if (dep.getUsedServices() != null  && dep.getUsedServices().size() != 0) {
                req.put("used",  getServiceReferenceList(dep.getUsedServices()));
            }
            
            array.put(req);
        }

        return array;
    }
    
    /**
     * Builds the JSON Array representing the given service reference list.
     * The array contains JSON objects. Those object contains the service id (id)
     * as well as the instance name (instance) if the property is set in the service
     * reference.
     * @param refs the service reference list
     * @return the JSON Array
     * @throws JSONException if the array cannot be created.
     */
    private JSONArray getServiceReferenceList(List<ServiceReference> refs) throws JSONException {
        JSONArray array = new JSONArray();
        if (refs != null) {
            for (ServiceReference ref : refs) {
                JSONObject reference = new JSONObject();
                if (ref.getProperty("instance.name") == null) {
                    reference.put("id", ref.getProperty(Constants.SERVICE_ID));
                } else {
                    reference.put("id", ref.getProperty(Constants.SERVICE_ID));
                    reference.put("instance", ref.getProperty("instance.name"));
                }
                array.put(reference);
            }
        }
        return array;
    }
    
    /**
     * Gets the plugin label.
     * @return the label.
     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#getLabel()
     */
    @Override
    public String getLabel() {
       return m_label;
    }

    /**
     * Gets the plugin title.
     * @return the title
     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#getTitle()
     */
    @Override
    public String getTitle() {
        return m_title;
    }
    
    /**
     * Get the CSS used by the plugin.
     * @return the list of CSS
     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#getCssReferences()
     */
    @Override
    protected String[] getCssReferences() {
        return CSS;
    }



    /**
     * Parse request to extract the query.
     */
    private final class RequestInfo {
        /**
         * The extension.
         */
        public final String extension;
        /**
         * The path.
         */
        public final String path;
        /**
         * The instances.
         */
        public final boolean instances;
        /**
         * The factories.
         */
        public final boolean factories;
        /**
         * The handlers.
         */
        public final boolean handlers;
        
        /**
         * The specific factory or instance name.
         */
        public final String name;
    
        
        /**
         * Creates a RequestInfo.
         * @param request the request
         */
        protected RequestInfo( final HttpServletRequest request ) {
            String info = request.getPathInfo();
            // remove label and starting slash
            info = info.substring(getLabel().length() + 1);
    
            // get extension
            if (info.endsWith(".json")) {
                extension = "json";
                info = info.substring(0, info.length() - 5);
            } else {
                extension = "html";
            }
    
            if (info.startsWith("/")) {
                path = info.substring(1);
    
                instances = path.startsWith("instances");
                factories = path.startsWith("factories");
                handlers = path.startsWith("handlers");
                
                if (instances  && path.startsWith("instances/")) {
                    name = path.substring("instances".length() + 1);
                } else if (factories  && path.startsWith("factories/")) {
                    name = path.substring("factories".length() + 1);
                } else {
                    name = null;
                }
            } else {
                path = null;
                name = null;
                instances = false;
                factories = false;
                handlers = false;
            }
           
            request.setAttribute(IPOJOPlugin.class.getName(), this);
        }
    
    }

}
