/*
 * 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 static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;

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.authentication.api.AuthenticationService;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.felix.dm.Component;
import org.apache.felix.dm.DependencyManager;
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.osgi.service.useradmin.User;
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 int BUFFER_SIZE = 1024 * 32;
    /** A boolean denoting whether or not authentication is enabled. */
    private static final String KEY_USE_AUTHENTICATION = "authentication.enabled";
    /** 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 DependencyManager m_dm;
    private volatile LogService m_log;
    private volatile AuthenticationService m_authService;
    private volatile ConnectionFactory m_connectionFactory;
    // See updated()
    private boolean m_useAuth = false;
    private URL m_obrURL;

    private final String m_repositoryXML = "repository.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 settings) throws ConfigurationException {
        if (settings != null) {
            String useAuthString = (String) settings.get(KEY_USE_AUTHENTICATION);
            if (useAuthString == null
                || !("true".equalsIgnoreCase(useAuthString) || "false".equalsIgnoreCase(useAuthString))) {
                throw new ConfigurationException(KEY_USE_AUTHENTICATION, "Missing or invalid value!");
            }
            boolean useAuth = Boolean.parseBoolean(useAuthString);
            m_useAuth = useAuth;

            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_useAuth = false;
            m_obrURL = null;
        }
    }

    /**
     * Called by Dependency Manager upon initialization of this component.
     * 
     * @param comp the component to initialize, cannot be <code>null</code>.
     */
    protected void init(Component comp) {
        comp.add(m_dm.createServiceDependency()
            .setService(AuthenticationService.class).setRequired(m_useAuth)
        );
    }

    @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);
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        if (!authenticate(req)) {
            // Authentication failed; don't proceed with the original request...
            resp.sendError(SC_UNAUTHORIZED);
        }
        else {
            // Authentication successful, proceed with original request...
            super.service(req, resp);
        }
    }

    /**
     * Authenticates, if needed the user with the information from the given request.
     * 
     * @param request
     *            the request to obtain the credentials from, cannot be <code>null</code>.
     * @return <code>true</code> if the authentication was successful, <code>false</code> otherwise.
     */
    private boolean authenticate(HttpServletRequest request) {
        if (m_useAuth) {
            User user = m_authService.authenticate(request);
            if (user == null) {
                m_log.log(LogService.LOG_INFO, "Authentication failure!");
            }
            return (user != null);
        }
        return true;
    }

    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 repository.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 repository.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<Version>();
        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;
    }
}
