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

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.StringUtil;
import org.apache.ofbiz.base.util.UtilGenerics;
import org.apache.ofbiz.base.util.UtilMisc;
import org.apache.ofbiz.base.util.UtilProperties;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.GenericEntityException;
import org.apache.ofbiz.entity.GenericValue;
import org.apache.ofbiz.entity.util.EntityQuery;
import org.apache.ofbiz.entityext.permission.EntityPermissionChecker;
import org.apache.ofbiz.security.Security;
import org.apache.ofbiz.service.DispatchContext;
import org.apache.ofbiz.service.GenericServiceException;
import org.apache.ofbiz.service.LocalDispatcher;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.service.ServiceUtil;


/**
 * ContentPermissionServices Class
 *
 * Services for granting operation permissions on Content entities in a data-driven manner.
 */
public class ContentPermissionServices {

    public static final String module = ContentPermissionServices.class.getName();
    public static final String resource = "ContentUiLabels";

    public ContentPermissionServices() {}

    /**
     * checkContentPermission
     *
     *@param dctx The DispatchContext that this service is operating in
     *@param context Map containing the input parameters
     *@return Map with the result of the service, the output parameters
     *
     * This service goes thru a series of test to determine if the user has
     * authority to performed anyone of the passed in target operations.
     *
     * It expects a Content entity in "currentContent"
     * It expects a list of contentOperationIds in "targetOperationList" rather
     * than a scalar because it is thought that sometimes more than one operation
     * would fit the situation.
     * Similarly, it expects a list of contentPurposeTypeIds in "contentPurposeList".
     * Again, normally there will just be one, but it is possible that a Content
     * entity could have multiple purposes associated with it.
     * The userLogin GenericValue is also required.
     * A list of roleTypeIds is also possible.
     *
     * The basic sequence of testing events is:
     * First the ContentPurposeOperation table is checked to see if there are any
     * entries with matching purposes (and operations) with no roleTypeId (ie. _NA_).
     * This is done because it would be the most common scenario and is quick to check.
     *
     * Secondly, the CONTENTMGR permission is checked.
     *
     * Thirdly, the ContentPurposeOperation table is rechecked to see if there are
     * any conditions with roleTypeIds that match associated ContentRoles tied to the
     * user.
     * If a Party of "PARTY_GROUP" type is found, the PartyRelationship table is checked
     * to see if the current user is linked to that group.
     *
     * If no match is found to this point and the current Content entity has a value for
     * ownerContentId, then the last step is recusively applied, using the ContentRoles
     * associated with the ownerContent entity.
     */
    public static Map<String, Object> checkContentPermission(DispatchContext dctx, Map<String, ? extends Object> context) {
        Debug.logWarning(new Exception(), "This service has been depricated in favor of [genericContentPermission]", module);

        Security security = dctx.getSecurity();
        Delegator delegator = dctx.getDelegator();
        //TODO this parameters is still not used but this service need to be replaced by genericContentPermission
        // String statusId = (String) context.get("statusId");
        //TODO this parameters is still not used but this service need to be replaced by genericContentPermission
        // String privilegeEnumId = (String) context.get("privilegeEnumId");
        GenericValue content = (GenericValue) context.get("currentContent");
        Boolean bDisplayFailCond = (Boolean)context.get("displayFailCond");
        boolean displayFailCond = false;
        if (bDisplayFailCond != null && bDisplayFailCond.booleanValue()) {
             displayFailCond = true;
        }
                Debug.logInfo("displayFailCond(0):" + displayFailCond, "");
        Boolean bDisplayPassCond = (Boolean)context.get("displayPassCond");
        boolean displayPassCond = false;
        if (bDisplayPassCond != null && bDisplayPassCond.booleanValue()) {
             displayPassCond = true;
        }
        Debug.logInfo("displayPassCond(0):" + displayPassCond, "");
        Map<String, Object> results = new HashMap<String, Object>();
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String partyId = (String) context.get("partyId");
        if (UtilValidate.isEmpty(partyId)) {
            String passedUserLoginId = (String)context.get("userLoginId");
            if (UtilValidate.isNotEmpty(passedUserLoginId)) {
                try {
                    userLogin = EntityQuery.use(delegator).from("UserLogin").where("userLoginId", passedUserLoginId).cache().queryOne();
                    if (userLogin != null) {
                        partyId = userLogin.getString("partyId");
                    }
                } catch (GenericEntityException e) {
                    return ServiceUtil.returnError(e.getMessage());
                }
            }
        }
        if (UtilValidate.isEmpty(partyId) && userLogin != null) {
            partyId = userLogin.getString("partyId");
        }


        // Do entity permission check. This will pass users with administrative permissions.
        boolean passed = false;
        // I realized, belatedly, that I wanted to be able to pass parameters in as
        // strings so this service could be used in an action event directly,
        // so I had to write this code to handle both list and strings
        List<String> passedPurposes = UtilGenerics.checkList(context.get("contentPurposeList"));
        String contentPurposeString = (String) context.get("contentPurposeString");
        if (UtilValidate.isNotEmpty(contentPurposeString)) {
            List<String> purposesFromString = StringUtil.split(contentPurposeString, "|");
            if (passedPurposes == null) {
                passedPurposes = new LinkedList<String>();
            }
            passedPurposes.addAll(purposesFromString);
        }

        EntityPermissionChecker.StdAuxiliaryValueGetter auxGetter = new EntityPermissionChecker.StdAuxiliaryValueGetter("ContentPurpose",  "contentPurposeTypeId", "contentId");
        // Sometimes permissions need to be checked before an entity is created, so
        // there needs to be a method for setting a purpose list
        auxGetter.setList(passedPurposes);
        List<String> targetOperations = UtilGenerics.checkList(context.get("targetOperationList"));
        String targetOperationString = (String) context.get("targetOperationString");
        if (UtilValidate.isNotEmpty(targetOperationString)) {
            List<String> operationsFromString = StringUtil.split(targetOperationString, "|");
            if (targetOperations == null) {
                targetOperations = new LinkedList<String>();
            }
            targetOperations.addAll(operationsFromString);
        }
        EntityPermissionChecker.StdPermissionConditionGetter permCondGetter = new EntityPermissionChecker.StdPermissionConditionGetter("ContentPurposeOperation",  "contentOperationId", "roleTypeId", "statusId", "contentPurposeTypeId", "privilegeEnumId");
        permCondGetter.setOperationList(targetOperations);

        EntityPermissionChecker.StdRelatedRoleGetter roleGetter = new EntityPermissionChecker.StdRelatedRoleGetter("Content",  "roleTypeId", "contentId", "partyId", "ownerContentId", "ContentRole");
        List<String> passedRoles = UtilGenerics.checkList(context.get("roleTypeList"));
        if (passedRoles == null) passedRoles = new LinkedList<String>();
        String roleTypeString = (String) context.get("roleTypeString");
        if (UtilValidate.isNotEmpty(roleTypeString)) {
            List<String> rolesFromString = StringUtil.split(roleTypeString, "|");
            passedRoles.addAll(rolesFromString);
        }
        roleGetter.setList(passedRoles);

        String entityAction = (String) context.get("entityOperation");
        if (entityAction == null) entityAction = "_ADMIN";
        if (userLogin != null && entityAction != null) {
            passed = security.hasEntityPermission("CONTENTMGR", entityAction, userLogin);
        }

        StringBuilder errBuf = new StringBuilder();
        String permissionStatus = null;
        List<Object> entityIds = new LinkedList<Object>();
        if (passed) {
            results.put("permissionStatus", "granted");
            permissionStatus = "granted";
            if (displayPassCond) {
                 errBuf.append("\n    hasEntityPermission(" + entityAction + "): PASSED");
            }

        } else {
            if (displayFailCond) {
                 errBuf.append("\n    hasEntityPermission(" + entityAction + "): FAILED");
            }

            if (content != null)
                entityIds.add(content);
            String quickCheckContentId = (String) context.get("quickCheckContentId");
            if (UtilValidate.isNotEmpty(quickCheckContentId)) {
               List<String> quickList = StringUtil.split(quickCheckContentId, "|");
               if (UtilValidate.isNotEmpty(quickList)) entityIds.addAll(quickList);
            }
            try {
                boolean check = EntityPermissionChecker.checkPermissionMethod(delegator, partyId,  "Content", entityIds, auxGetter, roleGetter, permCondGetter);
                if (check) {
                    results.put("permissionStatus", "granted");
                } else {
                    results.put("permissionStatus", "rejected");
                }
            } catch (GenericEntityException e) {
                return ServiceUtil.returnError(e.getMessage());
            }
            permissionStatus = (String)results.get("permissionStatus");
            errBuf.append("\n    permissionStatus:");
            errBuf.append(permissionStatus);
        }

        if ((permissionStatus.equals("granted") && displayPassCond)
            || (permissionStatus.equals("rejected") && displayFailCond)) {
            // Don't show this if passed on 'hasEntityPermission'
            if (displayFailCond || displayPassCond) {
              if (!passed) {
                 errBuf.append("\n    targetOperations:");
                 errBuf.append(targetOperations);

                 String errMsg = permCondGetter.dumpAsText();
                 errBuf.append("\n");
                 errBuf.append(errMsg);
                 errBuf.append("\n    partyId:");
                 errBuf.append(partyId);
                 errBuf.append("\n    entityIds:");
                 errBuf.append(entityIds);

                 if (auxGetter != null) {
                     errBuf.append("\n    auxList:");
                     errBuf.append(auxGetter.getList());
                 }

                 if (roleGetter != null) {
                     errBuf.append("\n    roleList:");
                     errBuf.append(roleGetter.getList());
                 }
              }

            }
        }
        Debug.logInfo("displayPass/FailCond(0), errBuf:" + errBuf.toString(), "");
        results.put(ModelService.ERROR_MESSAGE, errBuf.toString());
        return results;
    }

    public static Map<String, Object> checkAssocPermission(DispatchContext dctx, Map<String, ? extends Object> context) {
        Map<String, Object> results = new HashMap<String, Object>();
        // Security security = dctx.getSecurity();
        Delegator delegator = dctx.getDelegator();
        LocalDispatcher dispatcher = dctx.getDispatcher();
        Boolean bDisplayFailCond = (Boolean)context.get("displayFailCond");
        String contentIdFrom = (String) context.get("contentIdFrom");
        String contentIdTo = (String) context.get("contentIdTo");
        GenericValue userLogin = (GenericValue) context.get("userLogin");
        String entityAction = (String) context.get("entityOperation");
        Locale locale = (Locale) context.get("locale");
        if (entityAction == null) entityAction = "_ADMIN";
        String permissionStatus = null;

        GenericValue contentTo = null;
        GenericValue contentFrom = null;
        try {
            contentTo = EntityQuery.use(delegator).from("Content").where("contentId", contentIdTo).cache().queryOne();
            contentFrom = EntityQuery.use(delegator).from("Content").where("contentId", contentIdFrom).cache().queryOne();
        } catch (GenericEntityException e) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                    "ContentContentToOrFromErrorRetriving", locale));
        }
        if (contentTo == null || contentFrom == null) {
            return ServiceUtil.returnError(UtilProperties.getMessage(resource,
                    "ContentContentToOrFromIsNull", 
                    UtilMisc.toMap("contentTo", contentTo, "contentFrom", contentFrom), locale));
        }
        Map<String, Object> permResults = new HashMap<String, Object>();

        // Use the purposes from the from entity for both cases.
        List<String> relatedPurposes = EntityPermissionChecker.getRelatedPurposes(contentFrom, null);
        List<String> relatedPurposesTo = EntityPermissionChecker.getRelatedPurposes(contentTo, relatedPurposes);
        Map<String, Object> serviceInMap = new HashMap<String, Object>();
        serviceInMap.put("userLogin", userLogin);
        serviceInMap.put("targetOperationList", UtilMisc.toList("CONTENT_LINK_TO"));
        serviceInMap.put("contentPurposeList", relatedPurposesTo);
        serviceInMap.put("currentContent", contentTo);
        serviceInMap.put("displayFailCond", bDisplayFailCond);

        try {
            permResults = dispatcher.runSync("checkContentPermission", serviceInMap);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Problem checking permissions", "ContentServices");
        }
        permissionStatus = (String)permResults.get("permissionStatus");
        if (permissionStatus == null || !permissionStatus.equals("granted")) {
            if (bDisplayFailCond != null && bDisplayFailCond.booleanValue()) {
                String errMsg = (String)permResults.get(ModelService.ERROR_MESSAGE);
                results.put(ModelService.ERROR_MESSAGE, errMsg);
            }
            return results;
        }
        serviceInMap.put("currentContent", contentFrom);
        serviceInMap.put("targetOperationList", UtilMisc.toList("CONTENT_LINK_FROM"));
        serviceInMap.put("contentPurposeList", relatedPurposes);
        try {
            permResults = dispatcher.runSync("checkContentPermission", serviceInMap);
        } catch (GenericServiceException e) {
            Debug.logError(e, "Problem checking permissions", "ContentServices");
        }
        permissionStatus = (String)permResults.get("permissionStatus");
        if (permissionStatus != null && permissionStatus.equals("granted")) {
            results.put("permissionStatus", "granted");
        } else {
            if (bDisplayFailCond != null && bDisplayFailCond.booleanValue()) {
                String errMsg = (String)permResults.get(ModelService.ERROR_MESSAGE);
                results.put(ModelService.ERROR_MESSAGE, errMsg);
            }
        }
        return results;
    }

}
