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

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

import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.UtilDateTime;
import org.ofbiz.base.util.UtilMisc;
import org.ofbiz.base.util.UtilProperties;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.finder.PrimaryKeyFinder;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.entity.model.ModelField;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.ModelParam;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceDispatcher;
import org.ofbiz.service.ServiceUtil;

/**
 * Standard Java Static Method Service Engine
 */
public final class EntityAutoEngine extends GenericAsyncEngine {

    public static final String module = EntityAutoEngine.class.getName();
    public static final String resource = "ServiceErrorUiLabels";

    public EntityAutoEngine(ServiceDispatcher dispatcher) {
        super(dispatcher);
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runSyncIgnore(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
     */
    @Override
    public void runSyncIgnore(String localName, ModelService modelService, Map<String, Object> context) throws GenericServiceException {
        runSync(localName, modelService, context);
    }

    /**
     * @see org.ofbiz.service.engine.GenericEngine#runSync(java.lang.String, org.ofbiz.service.ModelService, java.util.Map)
     */
    @Override
    public Map<String, Object> runSync(String localName, ModelService modelService, Map<String, Object> parameters) throws GenericServiceException {
        // static java service methods should be: public Map<String, Object> methodName(DispatchContext dctx, Map<String, Object> context)
        DispatchContext dctx = dispatcher.getLocalContext(localName);
        Locale locale = (Locale) parameters.get("locale");
        Map<String, Object> localContext = new HashMap<String, Object>();
        localContext.put("parameters", parameters);
        Map<String, Object> result = ServiceUtil.returnSuccess();

        // check the package and method names
        if (modelService.invoke == null || (!"create".equals(modelService.invoke) && !"update".equals(modelService.invoke) && !"delete".equals(modelService.invoke))) {
            throw new GenericServiceException("In Service [" + modelService.name + "] the invoke value must be create, update, or delete for entity-auto engine");
        }

        if (UtilValidate.isEmpty(modelService.defaultEntityName)) {
            throw new GenericServiceException("In Service [" + modelService.name + "] you must specify a default-entity-name for entity-auto engine");
        }

        ModelEntity modelEntity = dctx.getDelegator().getModelEntity(modelService.defaultEntityName);
        if (modelEntity == null) {
            throw new GenericServiceException("In Service [" + modelService.name + "] the specified default-entity-name [" + modelService.defaultEntityName + "] is not valid");
        }

        try {
            boolean allPksInOnly = true;
            LinkedList<String> pkFieldNameOutOnly = null;
            /* Check for each pk if it's :
             * 1. part IN 
             * 2. or part IN and OUT, but without value but present on parameters map
             * Help the engine to determinate the operation to realize for a create call or validate that
             * any pk is present for update/delete call.
             */
            for (ModelField pkField: modelEntity.getPkFieldsUnmodifiable()) {
                ModelParam pkParam = modelService.getParam(pkField.getName());
                boolean pkValueInParameters = pkParam.isIn() && UtilValidate.isNotEmpty(parameters.get(pkParam.getFieldName()));
                if (pkParam.isOut() && !pkValueInParameters) {
                    if (pkFieldNameOutOnly == null) {
                        pkFieldNameOutOnly = new LinkedList();
                        allPksInOnly = false;
                    }
                    pkFieldNameOutOnly.add(pkField.getName());
                }
            }

            if ("create".equals(modelService.invoke)) {
                GenericValue newEntity = dctx.getDelegator().makeValue(modelEntity.getEntityName());

                boolean isSinglePk = modelEntity.getPksSize() == 1;
                boolean isDoublePk = modelEntity.getPksSize() == 2;
                Iterator<ModelField> pksIter = modelEntity.getPksIterator();

                ModelField singlePkModeField = isSinglePk ? pksIter.next() : null;
                ModelParam singlePkModelParam = isSinglePk ? modelService.getParam(singlePkModeField.getName()) : null;
                boolean isSinglePkIn = isSinglePk ? singlePkModelParam.isIn() : false;
                boolean isSinglePkOut = isSinglePk ? singlePkModelParam.isOut() : false;

                ModelParam doublePkPrimaryInParam = null;
                ModelParam doublePkSecondaryOutParam = null;
                ModelField doublePkSecondaryOutField = null;
                if (isDoublePk) {
                    ModelField firstPkField = pksIter.next();
                    ModelParam firstPkParam = modelService.getParam(firstPkField.getName());
                    ModelField secondPkField = pksIter.next();
                    ModelParam secondPkParam = modelService.getParam(secondPkField.getName());
                    if (firstPkParam.isIn() && secondPkParam.isOut()) {
                        doublePkPrimaryInParam = firstPkParam;
                        doublePkSecondaryOutParam = secondPkParam;
                        doublePkSecondaryOutField = secondPkField;
                    } else if (firstPkParam.isOut() && secondPkParam.isIn()) {
                        doublePkPrimaryInParam = secondPkParam;
                        doublePkSecondaryOutParam = firstPkParam;
                        doublePkSecondaryOutField = firstPkField;
                    } else {
                        // we don't have an IN and an OUT... so do nothing and leave them null
                    }
                }

                if (isSinglePk && isSinglePkOut && !isSinglePkIn) {
                    /*
                     **** primary sequenced primary key ****
                     *
                    <auto-attributes include="pk" mode="OUT" optional="false"/>
                     *
                    <make-value entity-name="Example" value-name="newEntity"/>
                    <sequenced-id-to-env sequence-name="Example" env-name="newEntity.exampleId"/> <!-- get the next sequenced ID -->
                    <field-to-result field-name="newEntity.exampleId" result-name="exampleId"/>
                    <set-nonpk-fields map-name="parameters" value-name="newEntity"/>
                    <create-value value-name="newEntity"/>
                     *
                     */

                    String sequencedId = dctx.getDelegator().getNextSeqId(modelEntity.getEntityName());
                    newEntity.set(singlePkModeField.getName(), sequencedId);
                } else if (isSinglePk && isSinglePkOut && isSinglePkIn) {
                    /*
                     **** primary sequenced key with optional override passed in ****
                     *
                    <auto-attributes include="pk" mode="INOUT" optional="true"/>
                     *
                    <make-value value-name="newEntity" entity-name="Product"/>
                    <set-nonpk-fields map-name="parameters" value-name="newEntity"/>
                    <set from-field="parameters.productId" field="newEntity.productId"/>
                    <if-empty field="newEntity.productId">
                        <sequenced-id-to-env sequence-name="Product" env-name="newEntity.productId"/>
                    <else>
                        <check-id field-name="productId" map-name="newEntity"/>
                        <check-errors/>
                    </else>
                    </if-empty>
                    <field-to-result field-name="productId" map-name="newEntity" result-name="productId"/>
                    <create-value value-name="newEntity"/>
                     *
                     */

                    Object pkValue = parameters.get(singlePkModelParam.name);
                    if (UtilValidate.isEmpty(pkValue)) {
                        pkValue = dctx.getDelegator().getNextSeqId(modelEntity.getEntityName());
                    } else {
                        // pkValue passed in, check and if there are problems return an error

                        if (pkValue instanceof String) {
                            StringBuffer errorDetails = new StringBuffer();
                            if (!UtilValidate.isValidDatabaseId((String) pkValue, errorDetails)) {
                                return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ServiceParameterValueNotValid", UtilMisc.toMap("parameterName", singlePkModelParam.name,"errorDetails", errorDetails), locale));
                            }
                        }
                    }
                    newEntity.set(singlePkModeField.getName(), pkValue);
                } else if (isDoublePk && doublePkPrimaryInParam != null && doublePkSecondaryOutParam != null) {
                    /*
                     **** secondary sequenced primary key ****
                     *
                    <auto-attributes include="pk" mode="IN" optional="false"/>
                    <override name="exampleItemSeqId" mode="OUT"/> <!-- make this OUT rather than IN, we will automatically generate the next sub-sequence ID -->
                     *
                    <make-value entity-name="ExampleItem" value-name="newEntity"/>
                    <set-pk-fields map-name="parameters" value-name="newEntity"/>
                    <make-next-seq-id value-name="newEntity" seq-field-name="exampleItemSeqId"/> <!-- this finds the next sub-sequence ID -->
                    <field-to-result field-name="newEntity.exampleItemSeqId" result-name="exampleItemSeqId"/>
                    <set-nonpk-fields map-name="parameters" value-name="newEntity"/>
                    <create-value value-name="newEntity"/>
                     */

                    newEntity.setPKFields(parameters, true);
                    dctx.getDelegator().setNextSubSeqId(newEntity, doublePkSecondaryOutField.getName(), 5, 1);
                } else if (allPksInOnly) {
                    /*
                     **** plain specified primary key ****
                     *
                    <auto-attributes include="pk" mode="IN" optional="false"/>
                     *
                    <make-value entity-name="Example" value-name="newEntity"/>
                    <set-pk-fields map-name="parameters" value-name="newEntity"/>
                    <set-nonpk-fields map-name="parameters" value-name="newEntity"/>
                    <create-value value-name="newEntity"/>
                     *
                     */
                    newEntity.setPKFields(parameters, true);
                    //with all pks present on parameters, check if the entity is not already exists.
                    GenericValue lookedUpValue = PrimaryKeyFinder.runFind(modelEntity, parameters, dctx.getDelegator(), false, true, null, null);
                    if (lookedUpValue != null) {
                        return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ServiceValueFound", UtilMisc.toMap("pkFields", newEntity.getPkShortValueString()), locale));
                    }
                } else {
                    /* We haven't all Pk and their are 3 or more, now check if isn't a associate entity with own sequence
                    <set-pk-fields map="parameters" value-field="newEntity"/>
                    <sequenced-id sequence-name="ExempleItemAssoc" field="newEntity.exempleItemAssocId"/>
                    <create-value value-field="newEntity"/>
                     */
                    if (pkFieldNameOutOnly != null && pkFieldNameOutOnly.size() == 1) {
                        newEntity.setPKFields(parameters, true);
                        String pkFieldName = pkFieldNameOutOnly.getFirst();
                        //if it's a fromDate, don't update it now, it's will be done next step
                        if (! "fromDate".equals(pkFieldName)) { 
                            String pkValue = dctx.getDelegator().getNextSeqId(modelEntity.getEntityName());
                            newEntity.set(pkFieldName, pkValue);
                        }
                    } else {
                        throw new GenericServiceException("In Service [" + modelService.name + "] which uses the entity-auto engine with the create invoke option: " +
                                "could not find a valid combination of primary key settings to do a known create operation; options include: " +
                                "1. a single OUT pk for primary auto-sequencing, " +
                                "2. a single INOUT pk for primary auto-sequencing with optional override, " +
                                "3. a 2-part pk with one part IN (existing primary pk) and one part OUT (the secondary pk to sub-sequence), " +
                                "4. a N-part pk with N-1 part IN and one party OUT only (missing pk is a sub-sequence mainly for entity assoc), " +
                                "5. all pk fields are IN for a manually specified primary key");
                    }
                }

                // handle the case where there is a fromDate in the pk of the entity, and it is optional or undefined in the service def, populate automatically
                ModelField fromDateField = modelEntity.getField("fromDate");
                if (fromDateField != null && fromDateField.getIsPk()) {
                    ModelParam fromDateParam = modelService.getParam("fromDate");
                    if (fromDateParam == null || parameters.get("fromDate") == null) {
                        newEntity.set("fromDate", UtilDateTime.nowTimestamp());
                    }
                }

                newEntity.setNonPKFields(parameters, true);
                if (modelEntity.getField("createdDate") != null) {
                    newEntity.set("createdDate", UtilDateTime.nowTimestamp());
                    if (modelEntity.getField("createdByUserLogin") != null) {
                        GenericValue userLogin = (GenericValue) parameters.get("userLogin");
                        if (userLogin != null) {
                            newEntity.set("createdByUserLogin", userLogin.get("userLoginId"));
                            if (modelEntity.getField("lastModifiedByUserLogin") != null) {
                                newEntity.set("lastModifiedByUserLogin", userLogin.get("userLoginId"));
                            }
                        }
                    }
                    if (modelEntity.getField("lastModifiedDate") != null) {
                        newEntity.set("lastModifiedDate", UtilDateTime.nowTimestamp());
                    }
                }
                newEntity.create();
                result.putAll(modelService.makeValid(newEntity, "OUT"));
            } else if ("update".equals(modelService.invoke)) {
                /*
                <auto-attributes include="pk" mode="IN" optional="false"/>
                 *
                <entity-one entity-name="ExampleItem" value-name="lookedUpValue"/>
                <set-nonpk-fields value-name="lookedUpValue" map-name="parameters"/>
                <store-value value-name="lookedUpValue"/>
                 */

                // check to make sure that all primary key fields are defined as IN attributes
                if (!allPksInOnly) {
                    throw new GenericServiceException("In Service [" + modelService.name + "] which uses the entity-auto engine with the update invoke option not all pk fields have the mode IN");
                }

                GenericValue lookedUpValue = PrimaryKeyFinder.runFind(modelEntity, parameters, dctx.getDelegator(), false, true, null, null);
                if (lookedUpValue == null) {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ServiceValueNotFound", locale));
                }

                localContext.put("lookedUpValue", lookedUpValue);

                // populate the oldStatusId out if there is a service parameter for it, and before we do the set non-pk fields
                /*
                <auto-attributes include="pk" mode="IN" optional="false"/>
                <attribute name="oldStatusId" type="String" mode="OUT" optional="false"/>
                 *
                <field-to-result field-name="lookedUpValue.statusId" result-name="oldStatusId"/>
                 */
                ModelParam statusIdParam = modelService.getParam("statusId");
                ModelField statusIdField = modelEntity.getField("statusId");
                ModelParam oldStatusIdParam = modelService.getParam("oldStatusId");
                if (statusIdParam != null && statusIdParam.isIn() && oldStatusIdParam != null && oldStatusIdParam.isOut() && statusIdField != null) {
                    result.put("oldStatusId", lookedUpValue.get("statusId"));
                }

                // do the StatusValidChange check
                /*
                <if-compare-field field="lookedUpValue.statusId" operator="not-equals" to-field="parameters.statusId">
                    <!-- if the record exists there should be a statusId, but just in case make it so it won't blow up -->
                    <if-not-empty field="lookedUpValue.statusId">
                        <!-- if statusId change is not in the StatusValidChange list, complain... -->
                        <entity-one entity-name="StatusValidChange" value-name="statusValidChange" auto-field-map="false">
                            <field-map field-name="statusId" env-name="lookedUpValue.statusId"/>
                            <field-map field-name="statusIdTo" env-name="parameters.statusId"/>
                        </entity-one>
                        <if-empty field="statusValidChange">
                            <!-- no valid change record found? return an error... -->
                            <add-error><fail-property resource="CommonUiLabels" property="CommonErrorNoStatusValidChange"/></add-error>
                            <check-errors/>
                        </if-empty>
                    </if-not-empty>
                </if-compare-field>
                 */
                String parameterStatusId = (String) parameters.get("statusId");
                if (statusIdParam != null && statusIdParam.isIn() && UtilValidate.isNotEmpty(parameterStatusId) && statusIdField != null) {
                    String lookedUpStatusId = (String) lookedUpValue.get("statusId");
                    if (UtilValidate.isNotEmpty(lookedUpStatusId) && !parameterStatusId.equals(lookedUpStatusId)) {
                        // there was an old status, and in this call we are trying to change it, so do the StatusValidChange check
                        GenericValue statusValidChange = dctx.getDelegator().findOne("StatusValidChange", true, "statusId", lookedUpStatusId, "statusIdTo", parameterStatusId);
                        if (statusValidChange == null) {
                            // uh-oh, no valid change...
                            return ServiceUtil.returnError(UtilProperties.getMessage("CommonUiLabels", "CommonErrorNoStatusValidChange", localContext, locale));
                        }
                    }
                }
                // NOTE: nothing here to maintain the status history, that should be done with a custom service called by SECA rule

                lookedUpValue.setNonPKFields(parameters, true);
                if (modelEntity.getField("lastModifiedDate") != null) {
                    lookedUpValue.set("lastModifiedDate", UtilDateTime.nowTimestamp());
                    if (modelEntity.getField("lastModifiedByUserLogin") != null) {
                        GenericValue userLogin = (GenericValue) parameters.get("userLogin");
                        if (userLogin != null) {
                            lookedUpValue.set("lastModifiedByUserLogin", userLogin.get("userLoginId"));
                        }
                    }
                }
                lookedUpValue.store();
            } else if ("delete".equals(modelService.invoke)) {
                /*
                <auto-attributes include="pk" mode="IN" optional="false"/>
                 *
                <entity-one entity-name="ExampleItem" value-name="lookedUpValue"/>
                <remove-value value-name="lookedUpValue"/>
                 */

                // check to make sure that all primary key fields are defined as IN attributes
                if (!allPksInOnly) {
                    throw new GenericServiceException("In Service [" + modelService.name + "] which uses the entity-auto engine with the delete invoke option not all pk fields have the mode IN");
                }

                GenericValue lookedUpValue = PrimaryKeyFinder.runFind(modelEntity, parameters, dctx.getDelegator(), false, true, null, null);
                if (lookedUpValue != null) {
                    lookedUpValue.remove();
                } else {
                    return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ServiceValueNotFoundForRemove", locale));
                }
            }
        } catch (GeneralException e) {
            Debug.logError(e, "Error doing entity-auto operation for entity [" + modelEntity.getEntityName() + "] in service [" + modelService.name + "]: " + e.toString(), module);
            return ServiceUtil.returnError(UtilProperties.getMessage(resource, "ServiceEntityAutoOperation", UtilMisc.toMap("entityName", modelEntity.getEntityName(), "serviceName", modelService.name,"errorString", e.toString()), locale));
        }

        return result;
    }
}
