/*
 * 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.ace.deployment.servlet;

import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.ace.connectionfactory.ConnectionFactory;
import org.osgi.framework.Version;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedService;
import org.osgi.service.log.LogService;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

public class AgentDeploymentServlet extends HttpServlet implements ManagedService {
    private static final long serialVersionUID = 1L;

    private static final int BUFFER_SIZE = 1024 * 32;

    /** URL to the OBR that is used for finding versions of the agent. */
    private static final String KEY_OBR_URL = "obr.url";

    private static final String XPATH_QUERY = "/repository/resource[@uri]";

    public static final String VERSIONS = "versions";
    public static final String BUNDLE_MIMETYPE = "application/octet-stream";
    public static final String TEXT_MIMETYPE = "text/plain";

    // injected by Dependency Manager
    private volatile LogService m_log;
    private volatile ConnectionFactory m_connectionFactory;
    // See updated()
    private URL m_obrURL;

    private final String m_repositoryXML = "index.xml";

    /**
     * Gets the actual text from a named item contained in the given node map.
     * 
     * @param map
     *            the node map to get the named item from;
     * @param name
     *            the name of the item to get.
     * @return the text of the named item, can be <code>null</code> in case the named item does not exist, or has no
     *         text.
     */
    private static String getNamedItemText(NamedNodeMap map, String name) {
        Node namedItem = map.getNamedItem(name);
        if (namedItem == null) {
            return null;
        }
        else {
            return namedItem.getTextContent();
        }
    }

    @Override
    public void updated(Dictionary<String, ?> settings) throws ConfigurationException {
        if (settings != null) {
            String obrURL = (String) settings.get(KEY_OBR_URL);
            try {
                URL url = new URL(obrURL);
                m_obrURL = url;
            }
            catch (MalformedURLException e) {
                throw new ConfigurationException(KEY_OBR_URL, "Invalid value, not a URL.", e);
            }
            if (obrURL == null) {
                throw new ConfigurationException(KEY_OBR_URL, "Missing " +
                    "value!");
            }
        }
        else {
            m_obrURL = null;
        }
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        try {
            String[] pathElements = verifyAndGetPathElements(request.getPathInfo());
            // String targetID = pathElements[1]; // in the future we might use this for per target approval
            String agentID = pathElements[2];
            int numberOfElements = pathElements.length;
            if (numberOfElements == 4) {
                handleVersionsRequest(getVersions(agentID), response);
            }
            else {
                handlePackageDelivery(agentID, new Version(pathElements[4]), request, response);
            }
        }
        catch (AceRestException e) {
            m_log.log(LogService.LOG_WARNING, e.getMessage(), e);
            if (!e.handleAsHttpError(response)) {
                m_log.log(LogService.LOG_ERROR, "Failed to properly notify client of exception!", e);
            }
        }
    }

    protected URLConnection openConnection(URL url) throws IOException {
        return m_connectionFactory.createConnection(url);
    }    

    private void closeSilently(Closeable resource) {
        try {
            if (resource != null) {
                resource.close();
            }
        }
        catch (IOException e) {
            m_log.log(LogService.LOG_WARNING, "Exception trying to close stream after request. ", e);
            throw new RuntimeException(e);
        }
    }

    private URL createOBRURL() throws MalformedURLException {
        try {
            return new URL(m_obrURL, m_repositoryXML);
        }
        catch (MalformedURLException e) {
            m_log.log(LogService.LOG_ERROR, "Error retrieving index.xml from " + m_obrURL);
            throw e;
        }
    }

    private InputStream getAgentFromOBR(URL obrBaseUrl, String agentID, Version version) throws XPathExpressionException, IOException {
        InputStream input = null;
        NodeList resources = getOBRNodeList(input);
        for (int nResource = 0; nResource < resources.getLength(); nResource++) {
            Node resource = resources.item(nResource);
            NamedNodeMap attr = resource.getAttributes();

            String uri = getNamedItemText(attr, "uri");
            if (uri == null || uri.equals("")) {
                m_log.log(LogService.LOG_ERROR, "Skipping resource without uri from repository " + obrBaseUrl);
                continue;
            }

            String symbolicname = getNamedItemText(attr, "symbolicname");
            Version bundleVersion = new Version(getNamedItemText(attr, "version"));
            if (agentID.equals(symbolicname) && version.equals(bundleVersion)) {
                URL url = new URL(obrBaseUrl, getNamedItemText(attr, "uri"));
                URLConnection connection = openConnection(url);
                return connection.getInputStream();
            }
        }
        return null;
    }

    private NodeList getOBRNodeList(InputStream input) throws XPathExpressionException, IOException {
        NodeList resources;
        try {
            URLConnection connection = openConnection(createOBRURL());
            // We always want the newest index.xml file.
            connection.setUseCaches(false);

            input = connection.getInputStream();

            try {
                XPath xpath = XPathFactory.newInstance().newXPath();
                // this XPath expressing will find all 'resource' elements which
                // have an attribute 'uri'.
                resources = (NodeList) xpath.evaluate(XPATH_QUERY, new InputSource(input), XPathConstants.NODESET);
            }
            catch (XPathExpressionException e) {
                m_log.log(LogService.LOG_ERROR, "Error evaluating XPath expression.", e);
                throw e;
            }
        }
        catch (IOException e) {
            m_log.log(LogService.LOG_ERROR, "Error reading repository metadata.", e);
            throw e;
        }
        finally {
            if (input != null) {
                try {
                    input.close();
                }
                catch (IOException e) {
                    // too bad, no worries.
                }
            }
        }
        return resources;
    }

    private List<Version> getVersions(String agentID) throws AceRestException {
        try {
            return getVersionsFromOBR(m_obrURL, agentID);
        }
        catch (XPathExpressionException e) {
            throw new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Unknown agent (" + agentID + ")");
        }
        catch (IOException ioe) {
            m_log.log(LogService.LOG_WARNING, "Error getting available versions.", ioe);
            throw new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Error getting available versions.");
        }
    }

    private List<Version> getVersionsFromOBR(URL obrBaseUrl, String agentID) throws XPathExpressionException, IOException {
        InputStream input = null;
        NodeList resources = getOBRNodeList(input);
        List<Version> obrList = new ArrayList<>();
        for (int nResource = 0; nResource < resources.getLength(); nResource++) {
            Node resource = resources.item(nResource);
            NamedNodeMap attr = resource.getAttributes();

            String uri = getNamedItemText(attr, "uri");
            if (uri == null || uri.equals("")) {
                m_log.log(LogService.LOG_ERROR, "Skipping resource without uri from repository " + obrBaseUrl);
                continue;
            }

            String symbolicname = getNamedItemText(attr, "symbolicname");
            if (agentID.equals(symbolicname)) {
                Version version = new Version(getNamedItemText(attr, "version"));
                obrList.add(version);
            }
        }
        Collections.sort(obrList);
        return obrList;
    }

    private void handlePackageDelivery(String agentID, Version version, HttpServletRequest request, HttpServletResponse response) throws AceRestException {
        InputStream is = null;
        OutputStream os = null;

        try {
            // Wrap response to add support for range requests
            response = new ContentRangeResponseWrapper(request, response);

            try {
                is = getAgentFromOBR(m_obrURL, agentID, version);
                if (is == null) {
                    throw (AceRestException) new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Agent not found in OBR.");
                }
            }
            catch (XPathExpressionException e) {
                throw (AceRestException) new AceRestException(HttpServletResponse.SC_NOT_FOUND, "Agent not found: error parsing OBR").initCause(e);
            }

            response.setContentType(BUNDLE_MIMETYPE);

            os = response.getOutputStream();
            byte[] buffer = new byte[BUFFER_SIZE];
            int bytes;
            while ((bytes = is.read(buffer)) != -1) {
                os.write(buffer, 0, bytes);
            }
            os.flush();
        }
        catch (IllegalArgumentException e) {
            throw (AceRestException) new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid").initCause(e);
        }
        catch (IOException e) {
            throw (AceRestException) new AceRestException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Could not deliver package").initCause(e);
        }
        finally {
            closeSilently(is);
            closeSilently(os);
        }
    }

    private void handleVersionsRequest(List<Version> versions, HttpServletResponse response) throws AceRestException {
        ServletOutputStream output = null;

        response.setContentType(TEXT_MIMETYPE);
        try {
            output = response.getOutputStream();
            for (Version version : versions) {
                output.print(version.toString());
                output.print("\n");
            }
        }
        catch (IOException e) {
            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid");
        }
        finally {
            closeSilently(output);
        }
    }

    private String[] verifyAndGetPathElements(String path) throws AceRestException {
        if (path == null) {
            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI is invalid, no path specified.");
        }
        String[] elements = path.split("/");
        int numberOfElements = elements.length;
        if ((numberOfElements < 4) || (numberOfElements > 5) || !VERSIONS.equals(elements[3])) {
            throw new AceRestException(HttpServletResponse.SC_BAD_REQUEST, "Request URI elements are invalid: " + path);
        }
        return elements;
    }
}
