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

import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.script.ScriptContext;
import javax.script.ScriptException;

import org.ofbiz.base.util.Assert;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.ScriptHelper;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.entity.Delegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericPK;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entity.model.ModelEntity;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;

/**
 * An implementation of the <code>ScriptHelper</code> interface.
 */
public final class ScriptHelperImpl implements ScriptHelper {

    public static final String module = ScriptHelperImpl.class.getName();
    private static final Map<String, ? extends Object> EMPTY_ARGS = Collections.unmodifiableMap(new HashMap<String, Object>());

    private static GenericValue runFindByPrimaryKey(ModelEntity modelEntity, ContextHelper ctxHelper, boolean useCache, boolean autoFieldMap,
            Map<String, ? extends Object> fieldMap, List<String> selectFieldList) throws ScriptException {
        Map<String, Object> entityContext = new HashMap<String, Object>();
        Delegator delegator = ctxHelper.getDelegator();
        Map<String, Object> context = ctxHelper.getBindings();
        if (autoFieldMap) {
            GenericValue tempVal = delegator.makeValue(modelEntity.getEntityName());
            Object parametersObj = context.get("parameters");
            if (parametersObj != null && parametersObj instanceof Map<?, ?>) {
                tempVal.setAllFields(UtilGenerics.checkMap(parametersObj), true, null, Boolean.TRUE);
            }
            tempVal.setAllFields(context, true, null, Boolean.TRUE);
            entityContext.putAll(tempVal);
        }
        if (fieldMap != null) {
            entityContext.putAll(fieldMap);
        }
        entityContext.put("locale", context.get("locale"));
        entityContext.put("timeZone", context.get("timeZone"));
        modelEntity.convertFieldMapInPlace(entityContext, delegator);
        entityContext.remove("locale");
        entityContext.remove("timeZone");
        Set<String> fieldsToSelect = null;
        if (selectFieldList != null) {
            fieldsToSelect = new HashSet<String>(selectFieldList);
        }
        if (fieldsToSelect != null && useCache) {
            String errMsg = "Error running script " + ctxHelper.getScriptName() + ": Problem invoking the findOne method: Cannot specify selectFieldList argument when useCache is set to true ";
            Debug.logWarning(errMsg, module);
            throw new ScriptException(errMsg);
        }
        GenericValue valueOut = null;
        GenericPK entityPK = delegator.makePK(modelEntity.getEntityName(), entityContext);
        if (entityPK.containsPrimaryKey(true)) {
            try {
                if (useCache) {
                    valueOut = delegator.findOne(entityPK.getEntityName(), entityPK, true);
                } else {
                    if (fieldsToSelect != null) {
                        valueOut = delegator.findByPrimaryKeyPartial(entityPK, fieldsToSelect);
                    } else {
                        valueOut = delegator.findOne(entityPK.getEntityName(), entityPK, false);
                    }
                }
            } catch (GenericEntityException e) {
                String errMsg = "Error running script " + ctxHelper.getScriptName() + ": Problem invoking the findOne method: " + e.getMessage();
                Debug.logWarning(e, errMsg, module);
                throw new ScriptException(errMsg);
            }
        } else {
            if (Debug.warningOn()) {
                Debug.logWarning("Error running script " + ctxHelper.getScriptName() + ": Returning null because found incomplete primary key in find: " + entityPK, module);
            }
        }
        return valueOut;
    }

    private final ContextHelper ctxHelper;

    public ScriptHelperImpl(ScriptContext context) {
        this.ctxHelper = new ContextHelper(context);
    }

    public Map<String, ? extends Object> createServiceMap(String serviceName, Map<String, ? extends Object> inputMap) throws ScriptException {
        Assert.notNull("serviceName", serviceName, "inputMap", inputMap);
        Map<String, Object> toMap = new HashMap<String, Object>();
        ModelService modelService = null;
        try {
            modelService = ctxHelper.getDispatcher().getDispatchContext().getModelService(serviceName);
        } catch (GenericServiceException e) {
            String errMsg = "Error running script " + ctxHelper.getScriptName() + ": Problem invoking the createServiceMap method: get service definition for service name [" + serviceName + "]: " + e.getMessage();
            Debug.logWarning(e, errMsg, module);
            throw new ScriptException(errMsg);
        }
        toMap.putAll(modelService.makeValid(inputMap, "IN", true, UtilGenerics.checkList(ctxHelper.getErrorMessages()), ctxHelper.getTimeZone(), ctxHelper.getLocale()));
        return toMap;
    }

    @Override
    public void error(String message) {
        if (ctxHelper.isEvent()) {
            ctxHelper.putResult("_error_message_", ctxHelper.expandString(message));
            ctxHelper.putResult("_response_code_", "error");
        } else if (ctxHelper.isService()) {
            ctxHelper.putResults(ServiceUtil.returnError(ctxHelper.expandString(message)));
        }
    }

    @Override
    public String evalString(String original) {
        return ctxHelper.expandString(original);
    }

    @Override
    public void failure(String message) {
        if (ctxHelper.isEvent()) {
            ctxHelper.putResult("_error_message_", ctxHelper.expandString(message));
            ctxHelper.putResult("_response_code_", "fail");
        } else if (ctxHelper.isService()) {
            ctxHelper.putResults(ServiceUtil.returnFailure(ctxHelper.expandString(message)));
        }
    }

    public List<Map<String, Object>> findList(String entityName, Map<String, ? extends Object> fields) throws ScriptException {
        try {
            return UtilGenerics.checkList(ctxHelper.getDelegator().findByAnd(entityName, fields, null, false));
        } catch (GenericEntityException e) {
            String errMsg = "Error running script " + ctxHelper.getScriptName() + ": Problem invoking the findList method: " + e.getMessage();
            Debug.logWarning(e, errMsg, module);
            throw new ScriptException(errMsg);
        }
    }

    public Map<String, Object> findOne(String entityName) throws ScriptException {
        return findOne(entityName, null, EMPTY_ARGS);
    }

    public Map<String, Object> findOne(String entityName, Map<String, ? extends Object> fields, Map<String, ? extends Object> args) throws ScriptException {
        Assert.notNull("entityName", entityName);
        if (args == null) {
            args = EMPTY_ARGS;
        }
        boolean useCache = "true".equals(args.get("useCache"));
        boolean autoFieldMap = !"false".equals(args.get("autoFieldMap"));
        List<String> selectFieldList = UtilGenerics.checkList(args.get("selectFieldList"));
        ModelEntity modelEntity = ctxHelper.getDelegator().getModelEntity(entityName);
        if (modelEntity == null) {
            throw new ScriptException("Error running script " + ctxHelper.getScriptName() + " - no entity definition found for entity name [" + entityName + "]");
        }
        return runFindByPrimaryKey(modelEntity, ctxHelper, useCache, autoFieldMap, fields, selectFieldList);
    }

    public void logError(String message) {
        String expandedMessage = ctxHelper.expandString(message);
        Debug.logError("[".concat(ctxHelper.getScriptName()).concat("] ").concat(expandedMessage), module);
    }

    public void logInfo(String message) {
        String expandedMessage = ctxHelper.expandString(message);
        Debug.logInfo("[".concat(ctxHelper.getScriptName()).concat("] ").concat(expandedMessage), module);
    }

    public void logWarning(String message) {
        String expandedMessage = ctxHelper.expandString(message);
        Debug.logWarning("[".concat(ctxHelper.getScriptName()).concat("] ").concat(expandedMessage), module);
    }

    public Map<String, Object> makeValue(String entityName) throws ScriptException {
        return ctxHelper.getDelegator().makeValidValue(entityName);
    }

    public Map<String, Object> makeValue(String entityName, Map<String, Object> fields) throws ScriptException {
        return ctxHelper.getDelegator().makeValidValue(entityName, fields);
    }

    public Map<String, ? extends Object> runService(String serviceName, Map<String, ? extends Object> inputMap) throws ScriptException {
        return runService(serviceName, inputMap, EMPTY_ARGS);
    }

    public Map<String, ? extends Object> runService(String serviceName, Map<String, ? extends Object> inputMap, Map<String, ? extends Object> args) throws ScriptException {
        Assert.notNull("serviceName", serviceName, "args", args);
        boolean includeUserLogin = !"false".equals(args.get("includeUserLoginStr"));
        String requireNewTransactionStr = (String) args.get("requireNewTransaction");
        int transactionTimeout = -1;
        if (UtilValidate.isNotEmpty(requireNewTransactionStr)) {
            String timeoutStr = (String) args.get("transactionTimout");
            if (!UtilValidate.isEmpty(timeoutStr)) {
                try {
                    transactionTimeout = Integer.parseInt(timeoutStr);
                } catch (NumberFormatException e) {
                    Debug.logWarning(e, "Setting timeout to 0 (default)", module);
                    transactionTimeout = 0;
                }
            }
        }
        Map<String, Object> inMap = new HashMap<String, Object>(inputMap);
        if (includeUserLogin && !inMap.containsKey("userLogin")) {
            GenericValue userLogin = ctxHelper.getUserLogin();
            if (userLogin != null) {
                inMap.put("userLogin", userLogin);
            }
        }
        if (!inMap.containsKey("locale") && ctxHelper.getLocale() != null) {
            inMap.put("locale", ctxHelper.getLocale());
        }
        if (!inMap.containsKey("timeZone") && ctxHelper.getTimeZone() != null) {
            inMap.put("timeZone", ctxHelper.getTimeZone());
        }
        Map<String, Object> result = null;
        try {
            if (UtilValidate.isEmpty(requireNewTransactionStr) && transactionTimeout < 0) {
                result = ctxHelper.getDispatcher().runSync(serviceName, inMap);
            } else {
                ModelService modelService = ctxHelper.getDispatcher().getDispatchContext().getModelService(serviceName);
                boolean requireNewTransaction = modelService.requireNewTransaction;
                int timeout = modelService.transactionTimeout;
                if (UtilValidate.isNotEmpty(requireNewTransactionStr)) {
                    requireNewTransaction = "true".equals(requireNewTransactionStr);
                }
                if (transactionTimeout >= 0) {
                    timeout = transactionTimeout;
                }
                result = ctxHelper.getDispatcher().runSync(serviceName, inMap, timeout, requireNewTransaction);
            }
        } catch (GenericServiceException e) {
            String errMsg = "Error running script " + ctxHelper.getScriptName() + " [problem invoking the [" + serviceName + "] service: " + e.getMessage();
            Debug.logWarning(e, errMsg, module);
            throw new ScriptException(errMsg);
        }
        return result;
    }

    @Override
    public void success() {
        if (ctxHelper.isEvent()) {
            ctxHelper.putResult("_response_code_", "success");
        } else if (ctxHelper.isService()) {
            ctxHelper.putResults(ServiceUtil.returnSuccess());
        }
    }

    @Override
    public void success(String message) {
        if (ctxHelper.isEvent()) {
            ctxHelper.putResult("_event_message_", ctxHelper.expandString(message));
            ctxHelper.putResult("_response_code_", "success");
        } else if (ctxHelper.isService()) {
            ctxHelper.putResults(ServiceUtil.returnSuccess(ctxHelper.expandString(message)));
        }
    }
}
