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

import org.apache.oozie.util.XLog;
import org.apache.oozie.util.ELEvaluator;
import org.apache.oozie.ErrorCode;
import org.apache.hadoop.conf.Configuration;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 * The ELService creates {@link ELEvaluator} instances preconfigured with constants and functions defined in the
 * configuration. <p> The following configuration parameters control the EL service: <p> {@link #CONF_CONSTANTS} list
 * of constant definitions to be available for EL evaluations. <p> {@link #CONF_FUNCTIONS} list of function definitions
 * to be available for EL evalations. <p> Definitions must be separated by a comma, definitions are trimmed. <p> The
 * syntax for a constant definition is <code>PREFIX:NAME=CLASS_NAME#CONSTANT_NAME</code>. <p> The syntax for a constant
 * definition is <code>PREFIX:NAME=CLASS_NAME#METHOD_NAME</code>.
 */
public class ELService implements Service {

    public static final String CONF_PREFIX = Service.CONF_PREFIX + "ELService.";

    public static final String CONF_CONSTANTS = CONF_PREFIX + "constants.";

    public static final String CONF_EXT_CONSTANTS = CONF_PREFIX + "ext.constants.";

    public static final String CONF_FUNCTIONS = CONF_PREFIX + "functions.";

    public static final String CONF_EXT_FUNCTIONS = CONF_PREFIX + "ext.functions.";

    public static final String CONF_GROUPS = CONF_PREFIX + "groups";

    private final XLog log = XLog.getLog(getClass());

    //<Group Name>, <List of constants>
    private HashMap<String, List<ELConstant>> constants;
    //<Group Name>, <List of functions>
    private HashMap<String, List<ELFunction>> functions;

    private static class ELConstant {
        private String name;
        private Object value;

        private ELConstant(String prefix, String name, Object value) {
            if (prefix.length() > 0) {
                name = prefix + ":" + name;
            }
            this.name = name;
            this.value = value;
        }
    }

    private static class ELFunction {
        private String prefix;
        private String name;
        private Method method;

        private ELFunction(String prefix, String name, Method method) {
            this.prefix = prefix;
            this.name = name;
            this.method = method;
        }
    }

    private List<ELService.ELConstant> extractConstants(Configuration conf, String key) throws ServiceException {
        List<ELService.ELConstant> list = new ArrayList<ELService.ELConstant>();
        if (conf.get(key, "").trim().length() > 0) {
            for (String function : ConfigurationService.getStrings(conf, key)) {
                String[] parts = parseDefinition(function);
                list.add(new ELConstant(parts[0], parts[1], findConstant(parts[2], parts[3])));
                log.trace("Registered prefix:constant[{0}:{1}] for class#field[{2}#{3}]", (Object[]) parts);
            }
        }
        return list;
    }

    private List<ELService.ELFunction> extractFunctions(Configuration conf, String key) throws ServiceException {
        List<ELService.ELFunction> list = new ArrayList<ELService.ELFunction>();
        if (conf.get(key, "").trim().length() > 0) {
            for (String function : ConfigurationService.getStrings(conf, key)) {
                String[] parts = parseDefinition(function);
                list.add(new ELFunction(parts[0], parts[1], findMethod(parts[2], parts[3])));
                log.trace("Registered prefix:constant[{0}:{1}] for class#field[{2}#{3}]", (Object[]) parts);
            }
        }
        return list;
    }

    /**
     * Initialize the EL service.
     *
     * @param services services instance.
     * @throws ServiceException thrown if the EL service could not be initialized.
     */
    @Override
    public synchronized void init(Services services) throws ServiceException {
        log.trace("Constants and functions registration");
        constants = new HashMap<String, List<ELConstant>>();
        functions = new HashMap<String, List<ELFunction>>();
        //Get the list of group names from configuration file
        // defined in the property tag: oozie.service.ELSerice.groups
        //String []groupList = services.getConf().get(CONF_GROUPS, "").trim().split(",");
        String[] groupList = ConfigurationService.getStrings(services.getConf(), CONF_GROUPS);
        //For each group, collect the required functions and constants
        // and store it into HashMap
        for (String group : groupList) {
            List<ELConstant> tmpConstants = new ArrayList<ELConstant>();
            tmpConstants.addAll(extractConstants(services.getConf(), CONF_CONSTANTS + group));
            tmpConstants.addAll(extractConstants(services.getConf(), CONF_EXT_CONSTANTS + group));
            constants.put(group, tmpConstants);
            List<ELFunction> tmpFunctions = new ArrayList<ELFunction>();
            tmpFunctions.addAll(extractFunctions(services.getConf(), CONF_FUNCTIONS + group));
            tmpFunctions.addAll(extractFunctions(services.getConf(), CONF_EXT_FUNCTIONS + group));
            functions.put(group, tmpFunctions);
        }
    }

    /**
     * Destroy the EL service.
     */
    @Override
    public void destroy() {
        constants = null;
        functions = null;
    }

    /**
     * Return the public interface for EL service.
     *
     * @return {@link ELService}.
     */
    @Override
    public Class<? extends Service> getInterface() {
        return ELService.class;
    }

    /**
     * Return an {@link ELEvaluator} pre-configured with the constants and functions for the specific group of
     * EL-functions and variables defined in the configuration. If the group name doesn't exist,
     * IllegalArgumentException is thrown
     * @param group: Name of the group of required EL Evaluator.
     * @return ELEvaluator a preconfigured {@link ELEvaluator}.
     */
    public ELEvaluator createEvaluator(String group) {
        ELEvaluator.Context context = new ELEvaluator.Context();
        boolean groupDefined = false;
        if (constants.containsKey(group)) {
            for (ELConstant constant : constants.get(group)) {
                context.setVariable(constant.name, constant.value);
            }
            groupDefined = true;
        }
        if (functions.containsKey(group)) {
            for (ELFunction function : functions.get(group)) {
                context.addFunction(function.prefix, function.name, function.method);
            }
            groupDefined = true;
        }
        if (groupDefined == false) {
            throw new IllegalArgumentException("Group " + group + " is not defined");
        }
        return new ELEvaluator(context);
    }

    private static String[] parseDefinition(String str) throws ServiceException {
        try {
            str = str.trim();
            if (!str.contains(":")) {
                str = ":" + str;
            }
            String[] parts = str.split(":");
            String prefix = parts[0];
            parts = parts[1].split("=");
            String name = parts[0];
            parts = parts[1].split("#");
            String klass = parts[0];
            String method = parts[1];
            return new String[]{prefix, name, klass, method};
        }
        catch (Exception ex) {
            throw new ServiceException(ErrorCode.E0110, str, ex.getMessage(), ex);
        }
    }

    public static Method findMethod(String className, String methodName) throws ServiceException {
        Method method = null;
        try {
            Class klass = Thread.currentThread().getContextClassLoader().loadClass(className);
            for (Method m : klass.getMethods()) {
                if (m.getName().equals(methodName)) {
                    method = m;
                    break;
                }
            }
            if (method == null) {
                throw new ServiceException(ErrorCode.E0111, className, methodName);
            }
            if ((method.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) != (Modifier.PUBLIC | Modifier.STATIC)) {
                throw new ServiceException(ErrorCode.E0112, className, methodName);
            }
        }
        catch (ClassNotFoundException ex) {
            throw new ServiceException(ErrorCode.E0113, className);
        }
        return method;
    }

    public static Object findConstant(String className, String constantName) throws ServiceException {
        try {
            Class klass = Thread.currentThread().getContextClassLoader().loadClass(className);
            Field field = klass.getField(constantName);
            if ((field.getModifiers() & (Modifier.PUBLIC | Modifier.STATIC)) != (Modifier.PUBLIC | Modifier.STATIC)) {
                throw new ServiceException(ErrorCode.E0114, className, constantName);
            }
            return field.get(null);
        }
        catch (IllegalAccessException ex) {
            throw new IllegalArgumentException(ex);
        }
        catch (NoSuchFieldException ex) {
            throw new ServiceException(ErrorCode.E0115, className, constantName);
        }
        catch (ClassNotFoundException ex) {
            throw new ServiceException(ErrorCode.E0113, className);
        }
    }

}
