/*
 * 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.webconsole.plugins.subsystem.internal;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

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

import org.apache.commons.fileupload.FileItem;
import org.apache.felix.utils.json.JSONWriter;
import org.apache.felix.webconsole.AbstractWebConsolePlugin;
import org.apache.felix.webconsole.DefaultVariableResolver;
import org.apache.felix.webconsole.SimpleWebConsolePlugin;
import org.apache.felix.webconsole.WebConsoleUtil;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.log.LogService;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.SubsystemConstants;

public class WebConsolePlugin extends SimpleWebConsolePlugin
{
    private static final long serialVersionUID = 4329827842860201817L;
    private static final String UNABLE_TO_FIND_TARGET_SUBSYSTEM = "Unable to find target subsystem";

    private static final String LABEL = "subsystems";
    private static final String TITLE = "Subsystems";
    private static final String CATEGORY = "OSGi";
    private static final String CSS[] = { "/res/ui/bundles.css" }; // yes, it's correct!
    private static final String RES = "/" + LABEL + "/res/";

    private final BundleContext bundleContext;
    private final String template;

    public WebConsolePlugin(BundleContext bc)
    {
        super(LABEL, TITLE, CSS);
        bundleContext = bc;

        template = readTemplateFile("/res/plugin.html");
    }

    @Override
    public String getCategory()
    {
        return CATEGORY;
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        String path = request.getPathInfo();
        // don't process if this is request to load a resource
        if (!path.startsWith(RES))
        {
            RequestInfo reqInfo = new RequestInfo(request);
            if (reqInfo.extension.equals("json"))
            {
                renderResult(response, reqInfo);

                // nothing more to do
                return;
            }
        }
        super.doGet(request, response);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
    {
        String action = WebConsoleUtil.getParameter(req, "action");
        if ("install".equals(action))
        {
            installSubsystem(req);

            if (req.getRequestURI().endsWith("/install")) {
                // just send 200/OK, no content
                resp.setContentLength( 0 );
            } else {
                // redirect to URL
                resp.sendRedirect(req.getRequestURI());
            }

            return;
        }
        else
        {
            boolean success = false;
            RequestInfo reqInfo = new RequestInfo(req);
            if ("start".equals(action))
            {
                startSubsystem(reqInfo.id);
                success = true;
            }
            else if ("stop".equals(action))
            {
                stopSubsystem(reqInfo.id);
                success = true;
            }
            else if ("uninstall".equals(action))
            {
                uninstallSubsystem(reqInfo.id);
                success = true;
            }
            else
            {
                super.doPost(req, resp);
            }

            if (success)
            {
                renderResult(resp, reqInfo);
            }
        }
    }

    private void installSubsystem(HttpServletRequest req) throws IOException
    {
        @SuppressWarnings("rawtypes")
        Map params = (Map) req.getAttribute( AbstractWebConsolePlugin.ATTR_FILEUPLOAD );

        final boolean start = getParameter(params, "subsystemstart") != null;
        FileItem[] subsystemItems = getFileItems(params, "subsystemfile");

        for (final FileItem subsystemItem : subsystemItems)
        {
            File tmpFile = null;
            try
            {
                // copy the data to a file for better processing
                tmpFile = File.createTempFile("installSubsystem", ".tmp");
                subsystemItem.write(tmpFile);
            }
            catch (Exception e)
            {
                log(LogService.LOG_ERROR, "Problem accessing uploaded subsystem file: " + subsystemItem.getName(), e);

                // remove the temporary file
                if (tmpFile != null)
                {
                    tmpFile.delete();
                    tmpFile = null;
                }
            }

            if (tmpFile != null)
            {
                final File file = tmpFile;
                // TODO support install in other subsystems than the root one
                // TODO currently this means that when installing more than one subsystem they
                // will be installed concurrently. Not sure if this is the best idea.
                // However the client UI does not support selecting more than one file, so
                // from a practical point of view this is currently not an issue.
                asyncSubsystemOperation(0, new SubsystemOperation()
                {
                    @Override
                    public void exec(Subsystem ss)
                    {
                        try
                        {
                            InputStream is = new FileInputStream(file);
                            try
                            {
                                Subsystem nss = ss.install("inputstream:" + subsystemItem.getName(), is);
                                if (start)
                                    nss.start();
                            }
                            finally
                            {
                                is.close();
                                file.delete();
                            }
                        }
                        catch (IOException e)
                        {
                            log(LogService.LOG_ERROR, "Problem installing subsystem", e);
                        }
                    }
                });
            }
        }
    }

    private void startSubsystem(long id) throws IOException
    {
        asyncSubsystemOperation(id, new SubsystemOperation()
        {
            // Lamba, where art thou. So close yet so far away...
            @Override
            public void exec(Subsystem ss)
            {
                ss.start();
            }
        });
    }

    private void stopSubsystem(long id) throws IOException
    {
        asyncSubsystemOperation(id, new SubsystemOperation()
        {
            @Override
            public void exec(Subsystem ss)
            {
                ss.stop();
            }
        });
    }

    private void uninstallSubsystem(long id) throws IOException
    {
        asyncSubsystemOperation(id, new SubsystemOperation()
        {
            @Override
            public void exec(Subsystem ss)
            {
                ss.uninstall();
            }
        });
    }

    private void asyncSubsystemOperation(long id, final SubsystemOperation op) throws IOException
    {
        try
        {
            Collection<ServiceReference<Subsystem>> refs =
                    bundleContext.getServiceReferences(Subsystem.class,
                            "(" + SubsystemConstants.SUBSYSTEM_ID_PROPERTY + "=" + id + ")");

            if (refs.size() < 1)
                throw new IOException(UNABLE_TO_FIND_TARGET_SUBSYSTEM);

            final ServiceReference<Subsystem> ref = refs.iterator().next();
            new Thread(new Runnable() {
                @Override
                public void run()
                {
                    Subsystem ss = bundleContext.getService(ref);
                    try
                    {
                        op.exec(ss);
                    }
                    finally
                    {
                        bundleContext.ungetService(ref);
                    }
                }
            }).start();
        }
        catch (InvalidSyntaxException e)
        {
            throw new IOException(e);
        }
    }

    @SuppressWarnings("rawtypes")
    private FileItem getParameter(Map params, String name)
    {
        FileItem[] items = (FileItem[]) params.get(name);
        if (items != null)
        {
            for (int i = 0; i < items.length; i++)
            {
                if (items[i].isFormField())
                {
                    return items[i];
                }
            }
        }

        // nothing found, fail
        return null;
    }

    @SuppressWarnings("rawtypes")
    private FileItem[] getFileItems(Map params, String name)
    {
        final List<FileItem> files = new ArrayList<FileItem>();
        FileItem[] items = (FileItem[]) params.get(name);
        if (items != null)
        {
            for (int i = 0; i < items.length; i++)
            {
                if (!items[i].isFormField() && items[i].getSize() > 0)
                {
                    files.add(items[i]);
                }
            }
        }

        return files.toArray(new FileItem[files.size()]);
    }

    @Override
    @SuppressWarnings("unchecked")
    protected void renderContent(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
    {
        RequestInfo reqInfo = getRequestInfo(req);

        StringWriter w = new StringWriter();
        PrintWriter w2 = new PrintWriter(w);
        renderResult(w2, reqInfo);

        // prepare variables
        DefaultVariableResolver vars = ((DefaultVariableResolver) WebConsoleUtil.getVariableResolver(req));
        vars.put("__data__", w.toString());

        res.getWriter().print(template);
    }

    private void renderResult(HttpServletResponse response, RequestInfo reqInfo) throws IOException
    {
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");
        renderResult(response.getWriter(), reqInfo);
    }

    private void renderResult(PrintWriter pw, RequestInfo reqInfo) throws IOException
    {
        JSONWriter jw = new JSONWriter(pw);
        jw.object();

        List<Subsystem> subsystems = getSubsystems();

        jw.key("status");
        jw.value(subsystems.size());

        jw.key("data");
        jw.array();
        for (Subsystem ss : subsystems)
        {
            subsystem(jw, ss);
        }
        jw.endArray();

        jw.endObject();
    }

    private void subsystem(JSONWriter jw, Subsystem ss) throws IOException
    {
        jw.object();

        jw.key("id");
        jw.value(ss.getSubsystemId());
        jw.key("name");
        jw.value(ss.getSymbolicName());
        jw.key("version");
        jw.value(ss.getVersion());
        jw.key("state");
        jw.value(ss.getState());

        jw.endObject();
    }

    private List<Subsystem> getSubsystems() throws IOException
    {
        try
        {
            List<Subsystem> l = new ArrayList<Subsystem>();
            for (ServiceReference<Subsystem> ref : bundleContext.getServiceReferences(Subsystem.class, null))
            {
                l.add(bundleContext.getService(ref));
            }
            return l;
        }
        catch (InvalidSyntaxException e)
        {
            throw new IOException(e);
        }
    }

    public SimpleWebConsolePlugin register()
    {
        return register(bundleContext);
    }

    static RequestInfo getRequestInfo(HttpServletRequest request)
    {
        return (RequestInfo) request.getAttribute(WebConsolePlugin.class.getName());
    }

    class RequestInfo
    {
        public final long id;
        public final Object extension;

        protected RequestInfo(HttpServletRequest req)
        {
            String info = req.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("/"))
                info = info.substring(1);

            if ("".equals(info))
                id = -1;
            else
                id = Long.parseLong(info);

            req.setAttribute(WebConsolePlugin.this.getClass().getName(), this);
        }
    }

    interface SubsystemOperation
    {
        void exec(Subsystem ss);
    }
}
