/**
 * 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;

import java.io.IOException;
import java.io.Writer;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import javax.servlet.ServletException;

import org.apache.hadoop.conf.Configuration;
import org.apache.oozie.client.CoordinatorAction;
import org.apache.oozie.client.CoordinatorJob;
import org.apache.oozie.client.WorkflowJob;
import org.apache.oozie.client.rest.BulkResponseImpl;
import org.apache.oozie.command.BulkJobsXCommand;
import org.apache.oozie.command.CommandException;
import org.apache.oozie.command.OperationType;
import org.apache.oozie.command.bundle.BulkBundleXCommand;
import org.apache.oozie.command.bundle.BundleJobChangeXCommand;
import org.apache.oozie.command.bundle.BundleJobResumeXCommand;
import org.apache.oozie.command.bundle.BundleJobSuspendXCommand;
import org.apache.oozie.command.bundle.BundleJobXCommand;
import org.apache.oozie.command.bundle.BundleJobsXCommand;
import org.apache.oozie.command.bundle.BundleKillXCommand;
import org.apache.oozie.command.bundle.BundleRerunXCommand;
import org.apache.oozie.command.bundle.BundleSLAAlertsDisableXCommand;
import org.apache.oozie.command.bundle.BundleSLAAlertsEnableXCommand;
import org.apache.oozie.command.bundle.BundleSLAChangeXCommand;
import org.apache.oozie.command.bundle.BundleStartXCommand;
import org.apache.oozie.command.bundle.BundleSubmitXCommand;
import org.apache.oozie.executor.jpa.BundleJobQueryExecutor;
import org.apache.oozie.executor.jpa.JPAExecutorException;
import org.apache.oozie.service.DagXLogInfoService;
import org.apache.oozie.service.Services;
import org.apache.oozie.service.XLogStreamingService;
import org.apache.oozie.util.DateUtils;
import org.apache.oozie.util.JobUtils;
import org.apache.oozie.util.JobsFilterUtils;
import org.apache.oozie.util.ParamChecker;
import org.apache.oozie.util.XLog;
import org.apache.oozie.util.XLogStreamer;

import com.google.common.annotations.VisibleForTesting;

public class BundleEngine extends BaseEngine {
    /**
     * Create a system Bundle engine, with no user and no group.
     */
    public BundleEngine() {
    }

    /**
     * Create a Bundle engine to perform operations on behave of a user.
     *
     * @param user user name.
     */
    public BundleEngine(String user) {
        this.user = ParamChecker.notEmpty(user, "user");
    }

    @Override
    public void change(String jobId, String changeValue) throws BundleEngineException {
        try {
            BundleJobChangeXCommand change = new BundleJobChangeXCommand(jobId, changeValue);
            change.call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    @Override
    public String dryRunSubmit(Configuration conf) throws BundleEngineException {
        BundleSubmitXCommand submit = new BundleSubmitXCommand(true, conf);
        try {
            String jobId = submit.call();
            return jobId;
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    @Override
    public CoordinatorJob getCoordJob(String jobId) throws BundleEngineException {
        throw new BundleEngineException(new XException(ErrorCode.E0301, "cannot get a coordinator job from BundleEngine"));
    }

    public BundleJobBean getBundleJob(String jobId) throws BundleEngineException {
        try {
            return new BundleJobXCommand(jobId).call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    @Override
    public CoordinatorJob getCoordJob(String jobId, String filter, int start, int length, boolean desc)
            throws BundleEngineException {
        throw new BundleEngineException(new XException(ErrorCode.E0301,
                "cannot get a coordinator job from BundleEngine"));
    }

    @Override
    public String getDefinition(String jobId) throws BundleEngineException {
        BundleJobBean job;
        try {
            job = new BundleJobXCommand(jobId).call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
        return job.getOrigJobXml();
    }

    @Override
    public WorkflowJob getJob(String jobId) throws BundleEngineException {
        throw new BundleEngineException(new XException(ErrorCode.E0301, "cannot get a workflow job from BundleEngine"));
    }

    @Override
    public WorkflowJob getJob(String jobId, int start, int length) throws BundleEngineException {
        throw new BundleEngineException(new XException(ErrorCode.E0301, "cannot get a workflow job from BundleEngine"));
    }

    @Override
    public String getJobIdForExternalId(String externalId) throws BundleEngineException {
        return null;
    }

    @Override
    public void kill(String jobId) throws BundleEngineException {
        try {
            new BundleKillXCommand(jobId).call();
        }
        catch (CommandException e) {
            throw new BundleEngineException(e);
        }
    }

    @Override
    @Deprecated
    public void reRun(String jobId, Configuration conf) throws BundleEngineException {
        throw new BundleEngineException(new XException(ErrorCode.E0301, "rerun"));
    }

    /**
     * Rerun Bundle actions for given rerunType
     *
     * @param jobId bundle job id
     * @param coordScope the rerun scope for coordinator job names separated by ","
     * @param dateScope the rerun scope for coordinator nominal times separated by ","
     * @param refresh true if user wants to refresh input/outpur dataset urls
     * @param noCleanup false if user wants to cleanup output events for given rerun actions
     * @throws BaseEngineException thrown if failed to rerun
     */
    public void reRun(String jobId, String coordScope, String dateScope, boolean refresh, boolean noCleanup)
            throws BaseEngineException {
        try {
            new BundleRerunXCommand(jobId, coordScope, dateScope, refresh, noCleanup).call();
        }
        catch (CommandException ex) {
            throw new BaseEngineException(ex);
        }
    }

    @Override
    public void resume(String jobId) throws BundleEngineException {
        BundleJobResumeXCommand resume = new BundleJobResumeXCommand(jobId);
        try {
            resume.call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    @Override
    public void start(String jobId) throws BundleEngineException {
        try {
            new BundleStartXCommand(jobId).call();
        }
        catch (CommandException e) {
            throw new BundleEngineException(e);
        }
    }

    protected void streamJobLog(XLogStreamer logStreamer, String jobId, Writer writer) throws IOException,
            BundleEngineException {
    try {
            BundleJobBean job;
            logStreamer.getXLogFilter().setParameter(DagXLogInfoService.JOB, jobId);
            job = new BundleJobXCommand(jobId).call();
            Date lastTime = null;
            if (job.isTerminalStatus()) {
                lastTime = job.getLastModifiedTime();
            }
            if (lastTime == null) {
                lastTime = new Date();
            }
            Services.get().get(XLogStreamingService.class)
                    .streamLog(logStreamer, job.getCreatedTime(), lastTime, writer);
        }
        catch (CommandException ex) {
            throw new IOException(ex);
        }
    }

    @Override
    public String submitJob(Configuration conf, boolean startJob) throws BundleEngineException {
        try {
            String jobId = new BundleSubmitXCommand(conf).call();

            if (startJob) {
                start(jobId);
            }
            return jobId;
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    @Override
    public void suspend(String jobId) throws BundleEngineException {
        BundleJobSuspendXCommand suspend = new BundleJobSuspendXCommand(jobId);
        try {
            suspend.call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    /**
     * Get bundle jobs
     *
     * @param filter the filter string
     * @param start start location for paging
     * @param len total length to get
     * @return bundle job info
     * @throws BundleEngineException thrown if failed to get bundle job info
     */
    public BundleJobInfo getBundleJobs(String filter, int start, int len) throws BundleEngineException {
        Map<String, List<String>> filterList = parseFilter(filter);

        try {
            return new BundleJobsXCommand(filterList, start, len).call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    /**
     * Parse filter string to a map with key = filter name and values = filter values
     *
     * @param filter the filter string
     * @return filter key and value map
     * @throws CoordinatorEngineException thrown if failed to parse filter string
     */
    @VisibleForTesting
    Map<String, List<String>> parseFilter(String filter) throws BundleEngineException {
        try {
            return JobsFilterUtils.parseFilter(filter);
        }
        catch (ServletException ex) {
            throw new BundleEngineException(ErrorCode.E0420, filter, ex.getMessage());
        }
    }

    /**
     * Get bulk job response
     *
     * @param bulkFilter the filter string
     * @param start start location for paging
     * @param len total length to get
     * @return bulk job info
     * @throws BundleEngineException thrown if failed to get bulk job info
     */
    public BulkResponseInfo getBulkJobs(String bulkFilter, int start, int len) throws BundleEngineException {
        Map<String,List<String>> bulkRequestMap = parseBulkFilter(bulkFilter);
        try {
            return new BulkJobsXCommand(bulkRequestMap, start, len).call();
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    /**
     * Parse filter string to a map with key = filter name and values = filter values
     * Allowed keys are defined as constants on top
     *
     * @param bulkParams the filter string
     * @return filter key-value pair map
     * @throws BundleEngineException thrown if failed to parse filter string
     */
    public static Map<String,List<String>> parseBulkFilter(String bulkParams) throws BundleEngineException {

        Map<String,List<String>> bulkFilter = new HashMap<String,List<String>>();
        // Functionality can be extended to different job levels - TODO extend filter parser and query
        // E.g. String filterlevel = "coordinatoraction"; BulkResponseImpl.BULK_FILTER_LEVEL
        if (bulkFilter != null) {
            StringTokenizer st = new StringTokenizer(bulkParams, ";");
            while (st.hasMoreTokens()) {
                String token = st.nextToken();
                if (token.contains("=")) {
                    String[] pair = token.split("=");
                    if (pair.length != 2) {
                        throw new BundleEngineException(ErrorCode.E0420, token,
                                "elements must be semicolon-separated name=value pairs");
                    }
                    pair[0] = pair[0].toLowerCase();
                    String[] values = pair[1].split(",");
                    if (!BulkResponseImpl.BULK_FILTER_NAMES.contains(pair[0])) {
                        throw new BundleEngineException(ErrorCode.E0420, token, XLog.format("invalid parameter name [{0}]",
                                pair[0]));
                    }
                    // special check and processing for time related params
                    if (pair[0].contains("time")) {
                        try {
                            DateUtils.parseDateUTC(pair[1]);
                        }
                        catch (ParseException e) {
                            throw new BundleEngineException(ErrorCode.E0420, token, XLog.format(
                                    "invalid value [{0}] for time. A datetime value of pattern [{1}] is expected", pair[1],
                                    DateUtils.ISO8601_UTC_MASK));
                        }
                    }
                    // special check for action status param
                    // TODO: when extended for levels other than coord action, check against corresponding level's Status values
                    if (pair[0].equals(BulkResponseImpl.BULK_FILTER_STATUS)) {
                        for(String value : values) {
                            try {
                                CoordinatorAction.Status.valueOf(value);
                            }
                            catch (IllegalArgumentException ex) {
                                throw new BundleEngineException(ErrorCode.E0420, token, XLog.format(
                                        "invalid action status [{0}]", value));
                            }
                        }
                    }
                    // eventually adding into map for all cases e.g. names, times, status
                    List<String> list = bulkFilter.get(pair[0]);
                    if (list == null) {
                        list = new ArrayList<String>();
                        bulkFilter.put(pair[0], list);
                    }
                    for(String value : values) {
                        value = value.trim();
                        if(value.isEmpty()) {
                            throw new BundleEngineException(ErrorCode.E0420, token, "value is empty or whitespace");
                        }
                        list.add(value);
                    }
                } else {
                    throw new BundleEngineException(ErrorCode.E0420, token,
                            "elements must be semicolon-separated name=value pairs");
                }
            }
            if (!bulkFilter.containsKey(BulkResponseImpl.BULK_FILTER_BUNDLE)) {
                throw new BundleEngineException(ErrorCode.E0305, BulkResponseImpl.BULK_FILTER_BUNDLE);
            }
        }
        return bulkFilter;
    }

    /**
     * Return the status for a Job ID
     *
     * @param jobId job Id.
     * @return the job's status
     * @throws BundleEngineException thrown if the job's status could not be obtained
     */
    @Override
    public String getJobStatus(String jobId) throws BundleEngineException {
        try {
            BundleJobBean bundleJob = BundleJobQueryExecutor.getInstance().get(
                    BundleJobQueryExecutor.BundleJobQuery.GET_BUNDLE_JOB_STATUS, jobId);
            return bundleJob.getStatusStr();
        }
        catch (JPAExecutorException e) {
            throw new BundleEngineException(e);
        }
    }

    @Override
    public void enableSLAAlert(String id, String actions, String dates, String childIds) throws BaseEngineException {
        try {
            new BundleSLAAlertsEnableXCommand(id, actions, dates, childIds).call();
        }
        catch (CommandException e) {
            throw new BundleEngineException(e);
        }
    }

    @Override
    public void disableSLAAlert(String id, String actions, String dates, String childIds) throws BaseEngineException {
        try {
            new BundleSLAAlertsDisableXCommand(id, actions, dates, childIds).call();
        }
        catch (CommandException e) {
            throw new BundleEngineException(e);
        }
    }

    @Override
    public void changeSLA(String id, String actions, String dates, String childIds, String newParams)
            throws BaseEngineException {
        Map<String, String> slaNewParams = null;
        try {

            if (newParams != null) {
                slaNewParams = JobUtils.parseChangeValue(newParams);
            }
            new BundleSLAChangeXCommand(id, actions, dates, childIds, slaNewParams).call();
        }
        catch (CommandException e) {
            throw new BundleEngineException(e);
        }
    }

    /**
     * return a list of killed Bundle job
     *
     * @param filter the filter string for which the bundle jobs are killed
     * @param start the starting index for bundle jobs
     * @param len maximum number of jobs to be killed
     * @return the list of jobs being killed
     * @throws BundleEngineException thrown if one or more of the jobs cannot be killed
     */
    public BundleJobInfo killJobs(String filter, int start, int len) throws BundleEngineException {
        try {
            Map<String, List<String>> filterList = parseFilter(filter);
            BundleJobInfo bundleJobInfo = new BulkBundleXCommand(filterList, start, len, OperationType.Kill).call();
            if (bundleJobInfo == null) {
                return new BundleJobInfo(new ArrayList<BundleJobBean>(), 0, 0, 0);
            }
            return bundleJobInfo;
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    /**
     * return a list of suspended Bundle job
     *
     * @param filter the filter string for which the bundle jobs are suspended
     * @param start the starting index for bundle jobs
     * @param len maximum number of jobs to be suspended
     * @return the list of jobs being suspended
     * @throws BundleEngineException thrown if one or more of the jobs cannot be suspended
     */
    public BundleJobInfo suspendJobs(String filter, int start, int len) throws BundleEngineException {
        try {
            Map<String, List<String>> filterList = parseFilter(filter);
            BundleJobInfo bundleJobInfo = new BulkBundleXCommand(filterList, start, len, OperationType.Suspend).call();
            if (bundleJobInfo == null) {
                return new BundleJobInfo(new ArrayList<BundleJobBean>(), 0, 0, 0);
            }
            return bundleJobInfo;
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }

    /**
     * return a list of resumed Bundle job
     *
     * @param filter the filter string for which the bundle jobs are resumed
     * @param start the starting index for bundle jobs
     * @param len maximum number of jobs to be resumed
     * @return the list of jobs being resumed
     * @throws BundleEngineException thrown if one or more of the jobs cannot be resumed
     */
    public BundleJobInfo resumeJobs(String filter, int start, int len) throws BundleEngineException {
        try {
            Map<String, List<String>> filterList = parseFilter(filter);
            BundleJobInfo bundleJobInfo = new BulkBundleXCommand(filterList, start, len, OperationType.Resume).call();
            if (bundleJobInfo == null) {
                return new BundleJobInfo(new ArrayList<BundleJobBean>(), 0, 0, 0);
            }
            return bundleJobInfo;
        }
        catch (CommandException ex) {
            throw new BundleEngineException(ex);
        }
    }
}
