/*******************************************************************************
 * 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.widget;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;

import org.apache.oro.text.regex.MalformedPatternException;
import org.apache.oro.text.regex.Pattern;
import org.apache.oro.text.regex.PatternMatcher;
import org.apache.oro.text.regex.Perl5Matcher;
import org.ofbiz.base.util.Debug;
import org.ofbiz.base.util.GeneralException;
import org.ofbiz.base.util.ObjectType;
import org.ofbiz.base.util.PatternFactory;
import org.ofbiz.base.util.UtilGenerics;
import org.ofbiz.base.util.UtilValidate;
import org.ofbiz.base.util.UtilXml;
import org.ofbiz.base.util.collections.FlexibleMapAccessor;
import org.ofbiz.base.util.string.FlexibleStringExpander;
import org.ofbiz.entity.GenericValue;
import org.ofbiz.entityext.permission.EntityPermissionChecker;
import org.ofbiz.minilang.operation.BaseCompare;
import org.ofbiz.security.Security;
import org.ofbiz.service.DispatchContext;
import org.ofbiz.service.GenericServiceException;
import org.ofbiz.service.LocalDispatcher;
import org.ofbiz.service.ModelService;
import org.ofbiz.service.ServiceUtil;
import org.w3c.dom.Element;

/**
 * Abstract base class for the condition models.
 */
@SuppressWarnings("serial")
public abstract class ModelWidgetCondition implements Serializable {

    /*
     * ----------------------------------------------------------------------- *
     *                     DEVELOPERS PLEASE READ
     * ----------------------------------------------------------------------- *
     * 
     * This model is intended to be a read-only data structure that represents
     * an XML element. Outside of object construction, the class should not
     * have any behaviors.
     * 
     * Instances of this class will be shared by multiple threads - therefore
     * it is immutable. DO NOT CHANGE THE OBJECT'S STATE AT RUN TIME!
     * 
     */

    public static final String module = ModelWidgetCondition.class.getName();
    public static final ConditionFactory DEFAULT_CONDITION_FACTORY = new DefaultConditionFactory();

    private final ModelWidget modelWidget;
    private final Condition rootCondition;

    protected ModelWidgetCondition(ConditionFactory factory, ModelWidget modelWidget, Element conditionElement) {
        this.modelWidget = modelWidget;
        Element firstChildElement = UtilXml.firstChildElement(conditionElement);
        this.rootCondition = factory.newInstance(modelWidget, firstChildElement);
    }

    public boolean eval(Map<String, Object> context) {
        return rootCondition.eval(context);
    }

    public ModelWidget getModelWidget() {
        return modelWidget;
    }

    public static List<Condition> readSubConditions(ConditionFactory factory, ModelWidget modelWidget, Element conditionElement) {
        List<? extends Element> subElementList = UtilXml.childElementList(conditionElement);
        List<Condition> condList = new ArrayList<Condition>(subElementList.size());
        for (Element subElement : subElementList) {
            condList.add(factory.newInstance(modelWidget, subElement));
        }
        return Collections.unmodifiableList(condList);
    }

    /**
     * Models the &lt;and&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class And extends ModelWidgetCondition implements Condition {
        private final List<Condition> subConditions;

        private And(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.subConditions = readSubConditions(factory, modelWidget, condElement);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            // return false for the first one in the list that is false, basic and algo
            for (Condition subCondition : this.subConditions) {
                if (!subCondition.eval(context)) {
                    return false;
                }
            }
            return true;
        }
    }

    public static interface Condition {
        boolean eval(Map<String, Object> context);
    }

    /**
     * A factory for <code>Condition</code> instances.
     *
     */
    public static interface ConditionFactory {
        /**
         * Returns a new <code>Condition</code> instance built from <code>conditionElement</code>.
         * 
         * @param modelWidget The <code>ModelWidget</code> that contains the <code>Condition</code> instance.
         * @param conditionElement The XML element used to build the <code>Condition</code> instance.
         * @return A new <code>Condition</code> instance built from <code>conditionElement</code>.
         * @throws IllegalArgumentException if no model was found for the XML element
         */
        Condition newInstance(ModelWidget modelWidget, Element conditionElement);
    }

    public static class DefaultConditionFactory implements ConditionFactory {
        public static final Condition TRUE = new Condition() {
            @Override
            public boolean eval(Map<String, Object> context) {
                return true;
            }
        };
        public static final Condition FALSE = new Condition() {
            @Override
            public boolean eval(Map<String, Object> context) {
                return false;
            }
        };

        public Condition newInstance(ModelWidget modelWidget, Element conditionElement) {
            if (conditionElement == null) {
                return TRUE;
            }
            if ("and".equals(conditionElement.getNodeName())) {
                return new And(this, modelWidget, conditionElement);
            } else if ("xor".equals(conditionElement.getNodeName())) {
                return new Xor(this, modelWidget, conditionElement);
            } else if ("or".equals(conditionElement.getNodeName())) {
                return new Or(this, modelWidget, conditionElement);
            } else if ("not".equals(conditionElement.getNodeName())) {
                return new Not(this, modelWidget, conditionElement);
            } else if ("if-service-permission".equals(conditionElement.getNodeName())) {
                return new IfServicePermission(this, modelWidget, conditionElement);
            } else if ("if-has-permission".equals(conditionElement.getNodeName())) {
                return new IfHasPermission(this, modelWidget, conditionElement);
            } else if ("if-validate-method".equals(conditionElement.getNodeName())) {
                return new IfValidateMethod(this, modelWidget, conditionElement);
            } else if ("if-compare".equals(conditionElement.getNodeName())) {
                return new IfCompare(this, modelWidget, conditionElement);
            } else if ("if-compare-field".equals(conditionElement.getNodeName())) {
                return new IfCompareField(this, modelWidget, conditionElement);
            } else if ("if-regexp".equals(conditionElement.getNodeName())) {
                return new IfRegexp(this, modelWidget, conditionElement);
            } else if ("if-empty".equals(conditionElement.getNodeName())) {
                return new IfEmpty(this, modelWidget, conditionElement);
            } else if ("if-entity-permission".equals(conditionElement.getNodeName())) {
                return new IfEntityPermission(this, modelWidget, conditionElement);
            } else {
                throw new IllegalArgumentException("Condition element not supported with name: " + conditionElement.getNodeName());
            }
        }
    }

    /**
     * Models the &lt;if-compare&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfCompare extends ModelWidgetCondition implements Condition {
        private final FlexibleMapAccessor<Object> fieldAcsr;
        private final FlexibleStringExpander formatExdr;
        private final String operator;
        private final String type;
        private final FlexibleStringExpander valueExdr;

        private IfCompare(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            String fieldAcsr = condElement.getAttribute("field");
            if (fieldAcsr.isEmpty())
                fieldAcsr = condElement.getAttribute("field-name");
            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
            this.valueExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("value"));
            this.operator = condElement.getAttribute("operator");
            this.type = condElement.getAttribute("type");
            this.formatExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("format"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            String value = this.valueExdr.expandString(context);
            String format = this.formatExdr.expandString(context);
            Object fieldVal = this.fieldAcsr.get(context);
            // always use an empty string by default
            if (fieldVal == null) {
                fieldVal = "";
            }
            List<Object> messages = new LinkedList<Object>();
            Boolean resultBool = BaseCompare.doRealCompare(fieldVal, value, operator, type, format, messages, null, null, true);
            if (messages.size() > 0) {
                messages.add(0, "Error with comparison in if-compare between field [" + fieldAcsr.toString() + "] with value ["
                        + fieldVal + "] and value [" + value + "] with operator [" + operator + "] and type [" + type + "]: ");

                StringBuilder fullString = new StringBuilder();
                for (Object item : messages) {
                    fullString.append(item.toString());
                }
                Debug.logWarning(fullString.toString(), module);
                throw new IllegalArgumentException(fullString.toString());
            }
            return resultBool.booleanValue();
        }
    }

    /**
     * Models the &lt;if-compare-field&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfCompareField extends ModelWidgetCondition implements Condition {
        private final FlexibleMapAccessor<Object> fieldAcsr;
        private final FlexibleStringExpander formatExdr;
        private final String operator;
        private final FlexibleMapAccessor<Object> toFieldAcsr;
        private final String type;

        private IfCompareField(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            String fieldAcsr = condElement.getAttribute("field");
            if (fieldAcsr.isEmpty())
                fieldAcsr = condElement.getAttribute("field-name");
            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
            String toFieldAcsr = condElement.getAttribute("to-field");
            if (toFieldAcsr.isEmpty())
                toFieldAcsr = condElement.getAttribute("to-field-name");
            this.toFieldAcsr = FlexibleMapAccessor.getInstance(toFieldAcsr);
            this.operator = condElement.getAttribute("operator");
            this.type = condElement.getAttribute("type");
            this.formatExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("format"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            String format = this.formatExdr.expandString(context);
            Object fieldVal = this.fieldAcsr.get(context);
            Object toFieldVal = this.toFieldAcsr.get(context);
            // always use an empty string by default
            if (fieldVal == null) {
                fieldVal = "";
            }
            List<Object> messages = new LinkedList<Object>();
            Boolean resultBool = BaseCompare.doRealCompare(fieldVal, toFieldVal, operator, type, format, messages, null, null,
                    false);
            if (messages.size() > 0) {
                messages.add(0, "Error with comparison in if-compare-field between field [" + fieldAcsr.toString()
                        + "] with value [" + fieldVal + "] and to-field [" + toFieldAcsr.toString() + "] with value ["
                        + toFieldVal + "] with operator [" + operator + "] and type [" + type + "]: ");

                StringBuilder fullString = new StringBuilder();
                for (Object item : messages) {
                    fullString.append(item.toString());
                }
                Debug.logWarning(fullString.toString(), module);
                throw new IllegalArgumentException(fullString.toString());
            }
            return resultBool.booleanValue();
        }
    }

    /**
     * Models the &lt;if-empty&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfEmpty extends ModelWidgetCondition implements Condition {
        private final FlexibleMapAccessor<Object> fieldAcsr;

        private IfEmpty(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            String fieldAcsr = condElement.getAttribute("field");
            if (fieldAcsr.isEmpty())
                fieldAcsr = condElement.getAttribute("field-name");
            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            Object fieldVal = this.fieldAcsr.get(context);
            return ObjectType.isEmpty(fieldVal);
        }
    }

    /**
     * Models the &lt;if-entity-permission&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfEntityPermission extends ModelWidgetCondition implements Condition {
        private final EntityPermissionChecker permissionChecker;

        private IfEntityPermission(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.permissionChecker = new EntityPermissionChecker(condElement);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            return permissionChecker.runPermissionCheck(context);
        }
    }

    /**
     * Models the &lt;if-has-permission&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfHasPermission extends ModelWidgetCondition implements Condition {
        private final FlexibleStringExpander actionExdr;
        private final FlexibleStringExpander permissionExdr;

        private IfHasPermission(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.permissionExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("permission"));
            this.actionExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("action"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            // if no user is logged in, treat as if the user does not have permission
            GenericValue userLogin = (GenericValue) context.get("userLogin");
            if (userLogin != null) {
                String permission = permissionExdr.expandString(context);
                String action = actionExdr.expandString(context);
                Security security = (Security) context.get("security");
                if (UtilValidate.isNotEmpty(action)) {
                    // run hasEntityPermission
                    if (security.hasEntityPermission(permission, action, userLogin)) {
                        return true;
                    }
                } else {
                    // run hasPermission
                    if (security.hasPermission(permission, userLogin)) {
                        return true;
                    }
                }
            }
            return false;
        }
    }

    /**
     * Models the &lt;if-regexp&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfRegexp extends ModelWidgetCondition implements Condition {
        private final FlexibleStringExpander exprExdr;
        private final FlexibleMapAccessor<Object> fieldAcsr;

        private IfRegexp(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            String fieldAcsr = condElement.getAttribute("field");
            if (fieldAcsr.isEmpty())
                fieldAcsr = condElement.getAttribute("field-name");
            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
            this.exprExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("expr"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            Object fieldVal = this.fieldAcsr.get(context);
            String expr = this.exprExdr.expandString(context);
            Pattern pattern;
            try {
                pattern = PatternFactory.createOrGetPerl5CompiledPattern(expr, true);
            } catch (MalformedPatternException e) {
                String errMsg = "Error in evaluation in if-regexp in screen: " + e.toString();
                Debug.logError(e, errMsg, module);
                throw new IllegalArgumentException(errMsg);
            }
            String fieldString = null;
            try {
                fieldString = (String) ObjectType.simpleTypeConvert(fieldVal, "String", null, (TimeZone) context.get("timeZone"),
                        (Locale) context.get("locale"), true);
            } catch (GeneralException e) {
                Debug.logError(e, "Could not convert object to String, using empty String", module);
            }
            // always use an empty string by default
            if (fieldString == null)
                fieldString = "";
            PatternMatcher matcher = new Perl5Matcher();
            return matcher.matches(fieldString, pattern);
        }
    }

    /**
     * Models the &lt;if-service-permission&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfServicePermission extends ModelWidgetCondition implements Condition {
        private final FlexibleStringExpander actionExdr;
        private final FlexibleStringExpander ctxMapExdr;
        private final FlexibleStringExpander resExdr;
        private final FlexibleStringExpander serviceExdr;

        private IfServicePermission(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.serviceExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("service-name"));
            this.actionExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("main-action"));
            this.ctxMapExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("context-map"));
            this.resExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("resource-description"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            // if no user is logged in, treat as if the user does not have permission
            GenericValue userLogin = (GenericValue) context.get("userLogin");
            if (userLogin != null) {
                String serviceName = serviceExdr.expandString(context);
                String mainAction = actionExdr.expandString(context);
                String contextMap = ctxMapExdr.expandString(context);
                String resource = resExdr.expandString(context);
                if (UtilValidate.isEmpty(resource)) {
                    resource = serviceName;
                }
                if (UtilValidate.isEmpty(serviceName)) {
                    Debug.logWarning("No permission service-name specified!", module);
                    return false;
                }
                Map<String, Object> serviceContext = UtilGenerics.toMap(context.get(contextMap));
                if (serviceContext != null) {
                    // copy the required internal fields
                    serviceContext.put("userLogin", context.get("userLogin"));
                    serviceContext.put("locale", context.get("locale"));
                } else {
                    serviceContext = context;
                }
                // get the service engine objects
                LocalDispatcher dispatcher = (LocalDispatcher) context.get("dispatcher");
                DispatchContext dctx = dispatcher.getDispatchContext();
                // get the service
                ModelService permService;
                try {
                    permService = dctx.getModelService(serviceName);
                } catch (GenericServiceException e) {
                    Debug.logError(e, module);
                    return false;
                }
                if (permService != null) {
                    // build the context
                    Map<String, Object> svcCtx = permService.makeValid(serviceContext, ModelService.IN_PARAM);
                    svcCtx.put("resourceDescription", resource);
                    if (UtilValidate.isNotEmpty(mainAction)) {
                        svcCtx.put("mainAction", mainAction);
                    }
                    // invoke the service
                    Map<String, Object> resp;
                    try {
                        resp = dispatcher.runSync(permService.name, svcCtx, 300, true);
                    } catch (GenericServiceException e) {
                        Debug.logError(e, module);
                        return false;
                    }
                    if (ServiceUtil.isError(resp) || ServiceUtil.isFailure(resp)) {
                        Debug.logError(ServiceUtil.getErrorMessage(resp), module);
                        return false;
                    }
                    Boolean hasPermission = (Boolean) resp.get("hasPermission");
                    if (hasPermission != null) {
                        return hasPermission.booleanValue();
                    }
                }
            }
            return false;
        }
    }

    /**
     * Models the &lt;if-validate-method&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class IfValidateMethod extends ModelWidgetCondition implements Condition {
        private final FlexibleStringExpander classExdr;
        private final FlexibleMapAccessor<Object> fieldAcsr;
        private final FlexibleStringExpander methodExdr;

        private IfValidateMethod(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            String fieldAcsr = condElement.getAttribute("field");
            if (fieldAcsr.isEmpty())
                fieldAcsr = condElement.getAttribute("field-name");
            this.fieldAcsr = FlexibleMapAccessor.getInstance(fieldAcsr);
            this.methodExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("method"));
            this.classExdr = FlexibleStringExpander.getInstance(condElement.getAttribute("class"));
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            String methodName = this.methodExdr.expandString(context);
            String className = this.classExdr.expandString(context);
            Object fieldVal = this.fieldAcsr.get(context);
            String fieldString = null;
            if (fieldVal != null) {
                try {
                    fieldString = (String) ObjectType.simpleTypeConvert(fieldVal, "String", null,
                            (TimeZone) context.get("timeZone"), (Locale) context.get("locale"), true);
                } catch (GeneralException e) {
                    Debug.logError(e, "Could not convert object to String, using empty String", module);
                }
            }
            // always use an empty string by default
            if (fieldString == null)
                fieldString = "";
            Class<?>[] paramTypes = new Class[] { String.class };
            Object[] params = new Object[] { fieldString };
            Class<?> valClass;
            try {
                valClass = ObjectType.loadClass(className);
            } catch (ClassNotFoundException cnfe) {
                Debug.logError("Could not find validation class: " + className, module);
                return false;
            }
            Method valMethod;
            try {
                valMethod = valClass.getMethod(methodName, paramTypes);
            } catch (NoSuchMethodException cnfe) {
                Debug.logError("Could not find validation method: " + methodName + " of class " + className, module);
                return false;
            }
            Boolean resultBool = Boolean.FALSE;
            try {
                resultBool = (Boolean) valMethod.invoke(null, params);
            } catch (Exception e) {
                Debug.logError(e, "Error in IfValidationMethod " + methodName + " of class " + className
                        + ", defaulting to false ", module);
            }
            return resultBool.booleanValue();
        }
    }

    /**
     * Models the &lt;not&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class Not extends ModelWidgetCondition implements Condition {
        private final Condition subCondition;

        private Not(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            Element firstChildElement = UtilXml.firstChildElement(condElement);
            this.subCondition = factory.newInstance(modelWidget, firstChildElement);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            return !this.subCondition.eval(context);
        }
    }

    /**
     * Models the &lt;or&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class Or extends ModelWidgetCondition implements Condition {
        private final List<Condition> subConditions;

        private Or(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.subConditions = readSubConditions(factory, modelWidget, condElement);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            // return true for the first one in the list that is true, basic or algo
            for (Condition subCondition : this.subConditions) {
                if (subCondition.eval(context)) {
                    return true;
                }
            }
            return false;
        }
    }

    /**
     * Models the &lt;xor&gt; element.
     * 
     * @see <code>widget-common.xsd</code>
     */
    public static class Xor extends ModelWidgetCondition implements Condition {
        private final List<Condition> subConditions;

        private Xor(ConditionFactory factory, ModelWidget modelWidget, Element condElement) {
            super(factory, modelWidget, condElement);
            this.subConditions = readSubConditions(factory, modelWidget, condElement);
        }

        @Override
        public boolean eval(Map<String, Object> context) {
            // if more than one is true stop immediately and return false; if all are false return false; if only one is true return true
            boolean foundOneTrue = false;
            for (Condition subCondition : this.subConditions) {
                if (subCondition.eval(context)) {
                    if (foundOneTrue) {
                        // now found two true, so return false
                        return false;
                    } else {
                        foundOneTrue = true;
                    }
                }
            }
            return foundOneTrue;
        }
    }
}
