/*******************************************************************************
 * 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.ofbiz.workeffort.workeffort;

import java.io.IOException;
import java.io.Writer;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

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

import javolution.util.FastList;
import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilHttp;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ServiceUtil;
import org.ofbiz.webapp.stats.VisitHandler;
import org.ofbiz.webapp.webdav.PropFindHelper;
import org.ofbiz.webapp.webdav.ResponseHelper;
import org.ofbiz.webapp.webdav.WebDavUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

/** iCalendar worker class. This class handles the WebDAV requests and
 * delegates the calendar conversion tasks to <code>ICalConverter</code>.
 */
public class ICalWorker {

    public static final String module = ICalWorker.class.getName();

    public static class ResponseProperties {
        public final int statusCode;
        public final String statusMessage;
        public ResponseProperties(int statusCode, String statusMessage) {
            this.statusCode = statusCode;
            this.statusMessage = statusMessage;
        }
    }

    protected static Map<String, Object> createConversionContext(HttpServletRequest request) {
        Map<String, Object> context = FastMap.newInstance();
        Enumeration<String> attributeEnum = UtilGenerics.cast(request.getAttributeNames());
        while (attributeEnum.hasMoreElements()) {
            String attributeName = attributeEnum.nextElement();
            context.put(attributeName, request.getAttribute(attributeName));
        }
        context.put("parameters", request.getParameterMap());
        context.put("locale", UtilHttp.getLocale(request));
        return context;
    }

    /** Create an HTTP Forbidden response. The calendar converter will use this
     * response when a user is logged in, but they don't have the basic CRUD
     * permissions to perform an action. Returning a Forbidden status will
     * prevent the client from trying the operation again.
     *
     * @param statusMessage Optional status message - usually <code>null</code>
     * for security reasons
     * @return Create an HTTP Forbidden response 
     */
    public static ResponseProperties createForbiddenResponse(String statusMessage) {
        return new ResponseProperties(HttpServletResponse.SC_FORBIDDEN, statusMessage);
    }

    /** Create an HTTP Unauthorized response. The calendar converter will use this
     * response when a user is not logged in, and basic CRUD permissions are
     * needed to perform an action. Returning an Unauthorized status will
     * force the client to authenticate the user, then try the operation again.
     *
     * @param statusMessage Optional status message - usually <code>null</code>
     * for security reasons
     * @return Create an HTTP Unauthorized response
     */
    public static ResponseProperties createNotAuthorizedResponse(String statusMessage) {
        return new ResponseProperties(HttpServletResponse.SC_UNAUTHORIZED, statusMessage);
    }

    public static ResponseProperties createNotFoundResponse(String statusMessage) {
        return new ResponseProperties(HttpServletResponse.SC_NOT_FOUND, statusMessage);
    }

    public static ResponseProperties createOkResponse(String statusMessage) {
        return new ResponseProperties(HttpServletResponse.SC_OK, statusMessage);
    }

    /** Create an HTTP Partial Content response. The calendar converter will use this
     * response when a calendar is only partially updated.
     *
     * @param statusMessage A message describing which calendar components were
     * not updated
     * @return Create an HTTP Partial Content response.
     */
    public static ResponseProperties createPartialContentResponse(String statusMessage) {
        return new ResponseProperties(HttpServletResponse.SC_PARTIAL_CONTENT, statusMessage);
    }

    protected static Date getLastModifiedDate(HttpServletRequest request) throws GenericEntityException {
        String workEffortId = (String) request.getAttribute("workEffortId");
        Delegator delegator = (Delegator) request.getAttribute("delegator");
        GenericValue publishProperties = EntityQuery.use(delegator).from("WorkEffort").where("workEffortId", workEffortId).queryOne();
        GenericValue iCalData = publishProperties.getRelatedOne("WorkEffortIcalData", false);
        if (iCalData != null) {
            return iCalData.getTimestamp("lastUpdatedStamp");
        } else {
            return publishProperties.getTimestamp("lastUpdatedStamp");
        }
    }

    public static void handleGetRequest(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException {
        if (!isValidRequest(request, response)) {
            return;
        }
        String workEffortId = (String) request.getAttribute("workEffortId");
        Debug.logInfo("[handleGetRequest] workEffortId = " + workEffortId, module);
        ResponseProperties responseProps = null;
        try {
            responseProps = ICalConverter.getICalendar(workEffortId, createConversionContext(request));
        } catch (Exception e) {
            Debug.logError(e, "[handleGetRequest] Error while sending calendar: ", module);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
        if (responseProps.statusCode == HttpServletResponse.SC_OK) {
            response.setContentType("text/calendar");
        }
        writeResponse(responseProps, request, response, context);
    }

    public static void handlePropFindRequest(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException {
        if (!isValidRequest(request, response)) {
            return;
        }
        String workEffortId = (String) request.getAttribute("workEffortId");
        Debug.logInfo("[handlePropFindRequest] workEffortId = " + workEffortId, module);
        try {
            Document requestDocument = WebDavUtil.getDocumentFromRequest(request);
            if (Debug.verboseOn()) {
                Debug.logVerbose("[handlePropFindRequest] PROPFIND body:\r\n" + UtilXml.writeXmlDocument(requestDocument), module);
            }
            PropFindHelper helper = new PropFindHelper(requestDocument);
            if (!helper.isAllProp() && !helper.isPropName()) {
                Document responseDocument = helper.getResponseDocument();
                List<Element> supportedProps = FastList.newInstance();
                List<Element> unSupportedProps = FastList.newInstance();
                List<Element> propElements = helper.getFindPropsList(ResponseHelper.DAV_NAMESPACE_URI);
                for (Element propElement : propElements) {
                    if ("getetag".equals(propElement.getNodeName())) {
                        Element etagElement = helper.createElementSetValue("D:getetag", String.valueOf(System.currentTimeMillis()));
                        supportedProps.add(etagElement);
                        continue;
                    }
                    if ("getlastmodified".equals(propElement.getNodeName())) {
                        Date lastModified = getLastModifiedDate(request);
                        Element lmElement = helper.createElementSetValue("D:getlastmodified", WebDavUtil.formatDate(WebDavUtil.RFC1123_DATE_FORMAT, lastModified));
                        supportedProps.add(lmElement);
                        continue;
                    }
                    unSupportedProps.add(responseDocument.createElementNS(propElement.getNamespaceURI(), propElement.getTagName()));
                }
                Element responseElement = helper.createResponseElement();
                responseElement.appendChild(helper.createHrefElement("/" + workEffortId + "/"));
                if (supportedProps.size() > 0) {
                    Element propElement = helper.createPropElement(supportedProps);
                    responseElement.appendChild(helper.createPropStatElement(propElement, ResponseHelper.STATUS_200));
                }
                if (unSupportedProps.size() > 0) {
                    Element propElement = helper.createPropElement(unSupportedProps);
                    responseElement.appendChild(helper.createPropStatElement(propElement, ResponseHelper.STATUS_404));
                }
                Element rootElement = helper.createMultiStatusElement();
                rootElement.appendChild(responseElement);
                responseDocument.appendChild(rootElement);
                if (Debug.verboseOn()) {
                    Debug.logVerbose("[handlePropFindRequest] PROPFIND response:\r\n" + UtilXml.writeXmlDocument(responseDocument), module);
                }
                ResponseHelper.prepareResponse(response, 207, "Multi-Status");
                Writer writer = response.getWriter();
                try {
                    helper.writeResponse(response, writer);
                } finally {
                    writer.close();
                }
                return;
            }
        } catch (Exception e) {
            Debug.logError(e, "PROPFIND error: ", module);
        }
        response.setStatus(HttpServletResponse.SC_OK);
        response.flushBuffer();
    }

    public static void handlePutRequest(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException {
        if (!isValidRequest(request, response)) {
            return;
        }
        String contentType = request.getContentType();
        if (contentType != null && !"text/calendar".equals(contentType)) {
            Debug.logInfo("[handlePutRequest] invalid content type", module);
            response.sendError(HttpServletResponse.SC_CONFLICT);
            return;
        }
        String workEffortId = (String) request.getAttribute("workEffortId");
        Debug.logInfo("[handlePutRequest] workEffortId = " + workEffortId, module);
        ResponseProperties responseProps = null;
        try {
            responseProps = ICalConverter.storeCalendar(request.getInputStream(), createConversionContext(request));
        } catch (Exception e) {
            Debug.logError(e, "[handlePutRequest] Error while updating calendar: ", module);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            return;
        }
        writeResponse(responseProps, request, response, context);
    }

    protected static boolean isValidRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
        if (!request.isSecure()) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return false;
        }
        setupRequest(request, response);
        String workEffortId = (String) request.getAttribute("workEffortId");
        if (workEffortId == null) {
            response.sendError(HttpServletResponse.SC_BAD_REQUEST);
            return false;
        }
        return true;
    }

    protected static void logInUser(HttpServletRequest request, HttpServletResponse response) throws GenericServiceException, GenericEntityException {
        Map<String, Object> serviceMap = WebDavUtil.getCredentialsFromRequest(request);
        if (serviceMap == null) {
            return;
        }
        serviceMap.put("locale", UtilHttp.getLocale(request));
        GenericValue userLogin = null;
        HttpSession session = request.getSession();
        LocalDispatcher dispatcher = (LocalDispatcher) request.getAttribute("dispatcher");
        Map<String, Object> result = dispatcher.runSync("userLogin", serviceMap);
        if (ServiceUtil.isError(result) || ServiceUtil.isFailure(result)) {
            return;
        }
        userLogin = (GenericValue) result.get("userLogin");
        request.setAttribute("userLogin", userLogin);
        session.setAttribute("userLogin", userLogin);
        VisitHandler.getVisitor(request, response);
        GenericValue person = userLogin.getRelatedOne("Person", false);
        if (person != null) {
            request.setAttribute("person", person);
        } else {
            GenericValue partyGroup = userLogin.getRelatedOne("PartyGroup", false);
            if (partyGroup != null) {
                request.setAttribute("partyGroup", partyGroup);
            }
        }
    }

    protected static void setupRequest(HttpServletRequest request, HttpServletResponse response) {
        String path = request.getPathInfo();
        if (UtilValidate.isEmpty(path)) {
            path = "/";
        }
        String workEffortId = path.substring(1);
        if (workEffortId.contains("/")) {
            workEffortId = workEffortId.substring(0, workEffortId.indexOf("/"));
        }
        if (workEffortId.length() < 1) {
            return;
        }
        request.setAttribute("workEffortId", workEffortId);
        try {
            logInUser(request, response);
        } catch (Exception e) {
            Debug.logError(e, "Error while logging in user: ", module);
        }
    }

    protected static void writeResponse(ResponseProperties responseProps, HttpServletRequest request, HttpServletResponse response, ServletContext context) throws IOException {
        if (Debug.verboseOn()) {
            Debug.logVerbose("Returning response: code = " + responseProps.statusCode +
                    ", message = " + responseProps.statusMessage, module);
        }
        response.setStatus(responseProps.statusCode);
        if (responseProps.statusCode == HttpServletResponse.SC_UNAUTHORIZED) {
            response.setHeader("WWW-Authenticate", "Basic realm=\"OFBiz iCalendar " + request.getAttribute("workEffortId") + "\"");
        }
        if (responseProps.statusMessage != null) {
            response.setContentLength(responseProps.statusMessage.length());
            Writer writer = response.getWriter();
            try {
                writer.write(responseProps.statusMessage);
            } finally {
                writer.close();
            }
        }
    }
}
