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

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

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

import javolution.util.FastMap;

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.StringUtil;
import org.ofbiz.base.util.UtilDateTime;
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.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.util.EntityQuery;
import org.ofbiz.security.Security;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.webapp.website.WebSiteWorker;



/**
 * ContentManagementEvents Class
 */
public class ContentManagementEvents {

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

    public static String updateStaticValues(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        Security security = (Security)request.getAttribute("security");
        GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
        ServletContext servletContext = session.getServletContext();
        String webSiteId = WebSiteWorker.getWebSiteId(request);
        Delegator delegator = (Delegator)request.getAttribute("delegator");
        LocalDispatcher dispatcher = (LocalDispatcher)request.getAttribute("dispatcher");
        Map<String, Object> paramMap = UtilHttp.getParameterMap(request);
        //if (Debug.infoOn()) Debug.logInfo("in updateStaticValues, paramMap:" + paramMap , module);
        String parentPlaceholderId = (String)paramMap.get("ph");
        if (UtilValidate.isEmpty(parentPlaceholderId)) {
            request.setAttribute("_ERROR_MESSAGE_", "ParentPlaceholder is empty.");
            return "error";
        }
        List<GenericValue> allPublishPointList = null;
        List<String []> permittedPublishPointList = null;
        List<Map<String, Object>> valueList = null;
        try {
            allPublishPointList = ContentManagementWorker.getAllPublishPoints(delegator, webSiteId);
            permittedPublishPointList = ContentManagementWorker.getPermittedPublishPoints(delegator, allPublishPointList, userLogin, security, "_ADMIN", null, null);
            valueList = ContentManagementWorker.getStaticValues(delegator, parentPlaceholderId, permittedPublishPointList);
        } catch (GeneralException e) {
            Debug.logError(e.getMessage(), module);
            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
            return "error";
        }
/*
        Set keySet = paramMap.keySet();
        Iterator itKeySet = keySet.iterator();
        Map contentIdLookup = FastMap.newInstance();
        while (itKeySet.hasNext()) {
            String idxAndContentId = (String)itKeySet.next();
            int pos = idxAndContentId.indexOf("_");
            if (pos > 0) {
                String idxStr = idxAndContentId.substring(0, pos);
                int idx = Integer.parseInt(idxStr);
                String contentId = idxAndContentId.substring(pos + 1);
                contentIdLookup.put(contentId, Integer.valueOf(idx));
            }
        }
*/

        int counter = 0;
        for (Map<String, Object> map : valueList) {
            String contentId = (String)map.get("contentId");
            //Integer idxObj = (Integer)contentIdLookup.get(contentId);
            //int idx = idxObj.intValue();
            for (String [] pubArr : permittedPublishPointList) {
                String pubContentId = pubArr[0];
                String pubValue = (String)map.get(pubContentId);
                String paramName = Integer.toString(counter)  + "_" + pubContentId;
                String paramValue = (String)paramMap.get(paramName);
                //if (Debug.infoOn()) Debug.logInfo("in updateStaticValues, contentId:" + contentId + " pubContentId:" + pubContentId + " pubValue:" + pubValue + " paramName:" + paramName + " paramValue:" + paramValue, module);
                Map<String, Object> serviceIn = FastMap.newInstance();
                serviceIn.put("userLogin", userLogin);
                serviceIn.put("contentIdTo", contentId);
                serviceIn.put("contentId", pubContentId);
                serviceIn.put("contentAssocTypeId", "SUBSITE");
                try {
                    if (UtilValidate.isNotEmpty(paramValue)) {
                        if (!paramValue.equals(pubValue)) {
                            if (paramValue.equalsIgnoreCase("Y")) {
                                serviceIn.put("fromDate", UtilDateTime.nowTimestamp());
                                dispatcher.runSync("createContentAssoc", serviceIn);
                            } else if (paramValue.equalsIgnoreCase("N") && pubValue.equalsIgnoreCase("Y")) {
                                serviceIn.put("thruDate", UtilDateTime.nowTimestamp());
                                Timestamp fromDate = (Timestamp)map.get(pubContentId + "FromDate");
                                serviceIn.put("fromDate", fromDate);
                                dispatcher.runSync("updateContentAssoc", serviceIn);
                            }
                        }
                    } else if (UtilValidate.isNotEmpty(pubValue)) {
                        if (pubValue.equalsIgnoreCase("Y")) {
                                serviceIn.put("thruDate", UtilDateTime.nowTimestamp());
                                Timestamp fromDate = (Timestamp)map.get(pubContentId + "FromDate");
                                serviceIn.put("fromDate", fromDate);
                                dispatcher.runSync("updateContentAssoc", serviceIn);
                        }
                    }
                } catch (GenericServiceException e) {
                    Debug.logError(e.getMessage(), module);
                    request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
                    return "error";
                }
            }
            counter++;
        }
        return "success";
    }

    public static String createStaticValue(HttpServletRequest request, HttpServletResponse response) {
        String retValue = "success";
        return retValue;
    }

    public static String updatePublishLinks(HttpServletRequest request, HttpServletResponse response) {
        HttpSession session = request.getSession();
        Security security = (Security)request.getAttribute("security");
        GenericValue userLogin = (GenericValue)session.getAttribute("userLogin");
        ServletContext servletContext = session.getServletContext();
        String webSiteId = WebSiteWorker.getWebSiteId(request);
        Delegator delegator = (Delegator)request.getAttribute("delegator");
        LocalDispatcher dispatcher = (LocalDispatcher)request.getAttribute("dispatcher");
        Map<String, Object> paramMap = UtilHttp.getParameterMap(request);
        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, paramMap:" + paramMap , module);
        String targContentId = (String)paramMap.get("contentId"); // The content to be linked to one or more sites
        String roles = null;
        String authorId = null;
        GenericValue authorContent = ContentManagementWorker.getAuthorContent(delegator, targContentId);
        if (authorContent != null) {
            authorId = authorContent.getString("contentId");
        } else {
            request.setAttribute("_ERROR_MESSAGE_", "authorContent is empty.");
            return "error";
        }

        // Determine if user is owner of target content
        String userLoginId = userLogin.getString("userLoginId");
        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, userLoginId:" + userLoginId + " authorId:" + authorId , module);
        List<String> roleTypeList = null;
        if (authorId != null && userLoginId != null && authorId.equals(userLoginId)) {
            roles = "OWNER";
            roleTypeList = StringUtil.split(roles, "|");
        }
        List<String> targetOperationList = UtilMisc.<String>toList("CONTENT_PUBLISH");
        List<String> contentPurposeList = null; //UtilMisc.toList("ARTICLE");
        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, roles:" + roles +" roleTypeList:" + roleTypeList , module);
        String permittedAction = (String)paramMap.get("permittedAction"); // The content to be linked to one or more sites
        String permittedOperations = (String)paramMap.get("permittedOperations"); // The content to be linked to one or more sites
        if (UtilValidate.isEmpty(targContentId)) {
            request.setAttribute("_ERROR_MESSAGE_", "targContentId is empty.");
            return "error";
        }

        // Get all the subSites that the user is permitted to link to
        List<Object []> origPublishedLinkList = null;
        try {
            // TODO: this needs to be given author userLogin
            EntityQuery.use(delegator).from("UserLogin").where("userLoginId", authorId).cache().queryOne();
            origPublishedLinkList = ContentManagementWorker.getPublishedLinks(delegator, targContentId, webSiteId, userLogin, security, permittedAction, permittedOperations, roles);
        } catch (GenericEntityException e) {
            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
            return "error";
        } catch (GeneralException e2) {
            request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
            return "error";
        }
                //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, origPublishedLinkList:" + origPublishedLinkList , module);

        // make a map of the values that are passed in using the top subSite as the key.
        // Content can only be linked to one subsite under a top site (ends with "_MASTER")
        Map<String, String> siteIdLookup = FastMap.newInstance();
        for (String param : paramMap.keySet()) {
            int pos = param.indexOf("select_");
                //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, param:" + param + " pos:" + pos , module);
            if (pos >= 0) {
                String siteId = param.substring(7);
                String subSiteVal = (String)paramMap.get(param);
                siteIdLookup.put(siteId, subSiteVal);
            }
        }
        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, siteIdLookup:" + siteIdLookup , module);

        // Loop thru all the possible subsites
        Timestamp nowTimestamp = UtilDateTime.nowTimestamp();
        // int counter = 0;
        String responseMessage = null;
        String errorMessage = null;
        // String permissionMessage = null;
        boolean statusIdUpdated = false;
        Map<String, Object> results = null;
        for (Object [] arr : origPublishedLinkList) {
            //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, arr:" + Arrays.asList(arr) , module);
            String contentId = (String)arr[0]; // main (2nd level) site id
            String origSubContentId = null;
            List<Object []> origSubList = UtilGenerics.checkList(arr[1]);
            // Timestamp topFromDate = (Timestamp)arr[3];
            Timestamp origFromDate = null;
            for (Object [] pubArr : origSubList) {
            // see if a link already exists by looking for non-null fromDate
                //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, pubArr:" + Arrays.asList(pubArr) , module);
                Timestamp fromDate = (Timestamp)pubArr[2];
                origSubContentId = null;
                if (fromDate != null) {
                    origSubContentId = (String)pubArr[0];
                    origFromDate = fromDate;
                    break;
                }
            }

            String currentSubContentId = siteIdLookup.get(contentId);
            //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, currentSubContentId:" + currentSubContentId , module);
            //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, origSubContentId:" + origSubContentId , module);
            try {
                if (UtilValidate.isNotEmpty(currentSubContentId)) {
                    if (!currentSubContentId.equals(origSubContentId)) {
                        // disable existing link
                        if (UtilValidate.isNotEmpty(origSubContentId) && origFromDate != null) {
                            List<GenericValue> oldActiveValues = EntityQuery.use(delegator).from("ContentAssoc")
                                    .where("contentId", targContentId, 
                                            "contentIdTo", origSubContentId, 
                                            "contentAssocTypeId", "PUBLISH_LINK", 
                                            "thruDate", null)
                                    .queryList();
                            for (GenericValue cAssoc : oldActiveValues) {
                                cAssoc.set("thruDate", nowTimestamp);
                                cAssoc.store();
                                //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, deactivating:" + cAssoc , module);
                            }
                        }
                        // create new link
                        Map<String, Object> serviceIn = FastMap.newInstance();
                        serviceIn.put("userLogin", userLogin);
                        serviceIn.put("contentId", targContentId);
                        serviceIn.put("contentAssocTypeId", "PUBLISH_LINK");
                        serviceIn.put("fromDate", nowTimestamp);
                        serviceIn.put("contentIdTo", currentSubContentId);
                        serviceIn.put("roleTypeList", roleTypeList);
                        serviceIn.put("targetOperationList", targetOperationList);
                        serviceIn.put("contentPurposeList", contentPurposeList);
                        results = dispatcher.runSync("createContentAssoc", serviceIn);
                        responseMessage = (String)results.get(ModelService.RESPONSE_MESSAGE);
                        if (UtilValidate.isNotEmpty(responseMessage)) {
                            errorMessage = (String)results.get(ModelService.ERROR_MESSAGE);
                            Debug.logError("in updatePublishLinks, serviceIn:" + serviceIn , module);
                            Debug.logError(errorMessage, module);
                            request.setAttribute("_ERROR_MESSAGE_", errorMessage);
                            return "error";
                        }

                        serviceIn = FastMap.newInstance();
                        serviceIn.put("userLogin", userLogin);
                        serviceIn.put("contentId", targContentId);
                        serviceIn.put("contentAssocTypeId", "PUBLISH_LINK");
                        serviceIn.put("fromDate", nowTimestamp);
                        serviceIn.put("contentIdTo", contentId);
                        serviceIn.put("roleTypeList", roleTypeList);
                        serviceIn.put("targetOperationList", targetOperationList);
                        serviceIn.put("contentPurposeList", contentPurposeList);
                        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, serviceIn(3b):" + serviceIn , module);
                        results = dispatcher.runSync("createContentAssoc", serviceIn);
                        //if (Debug.infoOn()) Debug.logInfo("in updatePublishLinks, results(3b):" + results , module);
                        if (!statusIdUpdated) {
                            try {
                                GenericValue targContent = EntityQuery.use(delegator).from("Content").where("contentId", targContentId).queryOne();
                                targContent.set("statusId", "CTNT_PUBLISHED");
                                targContent.store();
                                statusIdUpdated = true;
                            } catch (GenericEntityException e) {
                                Debug.logError(e.getMessage(), module);
                                request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
                                return "error";
                            }
                        }
                    }
                } else if (UtilValidate.isNotEmpty(origSubContentId)) {
                    // if no current link is passed in, look to see if there is an existing link(s) that must be disabled
                    List<GenericValue> oldActiveValues = EntityQuery.use(delegator).from("ContentAssoc")
                            .where("contentId", targContentId, 
                                    "contentIdTo", origSubContentId, 
                                    "contentAssocTypeId", "PUBLISH_LINK", 
                                    "thruDate", null)
                            .queryList();
                    for (GenericValue cAssoc : oldActiveValues) {
                        cAssoc.set("thruDate", nowTimestamp);
                        cAssoc.store();
                    }
                }
            } catch (GenericEntityException e) {
                Debug.logError(e.getMessage(), module);
                request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
                return "error";
            } catch (GenericServiceException e2) {
                Debug.logError(e2, module);
                request.setAttribute("_ERROR_MESSAGE_", e2.getMessage());
                return "error";
            }
        }
        return "success";
    }

}
