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

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.pmapi.InvalidRequestException;
import org.apache.ode.utils.ISO8601DateParser;
import org.apache.ode.utils.RelativeDateParser;

import java.io.Serializable;
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;

/**
 * Holds a filter that will get interpreted when listing processe instances. The
 * semantic of the filtering is somewhat different than the one used in the
 * ProcessQuery class. Here we're introducing a pseudo process querying
 * language.
 */
public class InstanceFilter extends Filter<InstanceFilter.Criteria> implements Serializable {
    protected static Logger LOG = LoggerFactory.getLogger(InstanceFilter.class);

    private static final long serialVersionUID = 9999;

    /** If set, will filter on the instance id (IID) and select all matching instances */
    private List<String> iids;

    /** If set, will filter on the process id (PID) and select all matching process definitions */
    private List<String> pids;

    /** If set, the PID filter will work negatively */
    private boolean arePidsNegative;

    /** If set, will filter on the process name (accepts ending with wildcard) */
    private String nameFilter;

    /** If set, will filter on the process name (accepts ending with wildcard) */
    private String namespaceFilter;

    /**
     * If set, will filter on the instance status. Status being exclusive,
     * statuses are joined with an 'or'.
     */
    private List<String> statusFilter;

    /**
     * If set, will filter on the process started date. Prefixed with a comparison
     * operator (<, >, <=, >=, =). We're keeping a string and note converting to
     * a java date as ISO string dates are much easier and quicker to manipulate.
     * It's possible to have more than one date filter to handle the 'between'
     * case.
     */
    private List<String> startedDateFilter;

    /** If set, will filter on the process last active date. */
    private List<String> lastActiveDateFilter;

    private Map<String, String> propertyValuesFilter;

    /**
     * Orders to use when sorting the result (no particular order if not set).
     * Currently /supported keys are:
     * <ul>
     * <li>pid</li>
     * <li>name</li>
     * <li>namespace</li>
     * <li>version</li>
     * <li>status</li>
     * <li>started</li>
     * <li>last-active</li>
     * </ul>
     * Each key can be prefixed with a + or - sign for ascending or descending
     * orders (ascending if no sign specified)..
     */
    public List<String> orders;

    private int limit;

    /**
     * Known criteria (and a means to process them).
     */
    enum Criteria {
        IID {
            void process(InstanceFilter filter, String key, String op, String value) {
                filter.iids = parse(value);
            }
        },
        PID {
            void process(InstanceFilter filter, String key, String op, String value) {
                filter.pids = parse(value);
                filter.arePidsNegative = "<>".equals(op);
            }
        },
        NAME {
            void process(InstanceFilter filter, String key, String op, String value) {
                filter.nameFilter = value;
            }
        },
        NAMESPACE {
            void process(InstanceFilter filter, String key, String op, String value) {
                filter.namespaceFilter = value;
            }
        },
        STATUS {
            void process(InstanceFilter filter, String key, String op, String value) {
                filter.statusFilter = parse(value);
            }
        },
        STARTED {
            void process(InstanceFilter filter, String key, String op, String value) {
                if (filter.startedDateFilter == null)
                    filter.startedDateFilter = new ArrayList<String>();
                filter.startedDateFilter.add(op + value);
            }
        },
        LAST_ACTIVE {
            void process(InstanceFilter filter, String key, String op, String value) {
                if (filter.lastActiveDateFilter == null)
                    filter.lastActiveDateFilter = new ArrayList<String>();
                filter.lastActiveDateFilter.add(op + value);
            }
        },
        PROPERTY {
            void process(InstanceFilter filter, String key, String op, String value) {
                if (filter.propertyValuesFilter == null)
                    filter.propertyValuesFilter = new HashMap<String, String>(5);
                filter.propertyValuesFilter.put(key.substring(1, key.length()), value);
            }
        };

        abstract void process(InstanceFilter filter, String key, String op, String value);
    }

    enum OrderKeys {
        PID, NAME, NAMESPACE, VERSION, STATUS, STARTED, LAST_ACTIVE;
    }

    public enum StatusKeys {
        ACTIVE, SUSPENDED, ERROR, COMPLETED, TERMINATED, FAILED, FAULTED;
    }

    /**
     * Initializes properly the InstanceFilter attributes by pre-parsing the
     * filter and orderKeys strings and setting the limit. A limit inferior than
     * or equal to 0 is ignored.
     *
     * @param filter
     * @param orderKeys
     */
    public InstanceFilter(String filter, String orderKeys, int limit) {
        init(filter);

        // Some additional validation on status values
        if (statusFilter != null) {
            for (String status : statusFilter) {
                try {
                    StatusKeys.valueOf(status.toUpperCase());
                } catch (IllegalArgumentException e) {
                    throw new InvalidRequestException(
                            "The status you're using in your filter isn't valid, "
                                    + "only the active, suspended, error, completed, terminated and faulted status are "
                                    + "valid. " + e.toString());
                }
            }
        }
        // Some additional validation on date format value
        if (startedDateFilter != null) {
            for (String ddf : startedDateFilter) {
                try {
                    parseDateExpression(getDateWithoutOp(ddf));
                } catch (ParseException e) {
                    throw new InvalidRequestException(
                            "Couldn't parse one of the filter date, please make "
                                    + "sure it follows the ISO-8601 date or date/time standard (yyyyMMddhhmmss). "
                                    + e.toString());
                }
            }
        }
        if (lastActiveDateFilter != null) {
            for (String ddf : lastActiveDateFilter) {
                try {
                    parseDateExpression(getDateWithoutOp(ddf));
                } catch (ParseException e) {
                    throw new InvalidRequestException(
                            "Couldn't parse one of the filter date, please make "
                                    + "sure it follows the ISO-8601 date or date/time standard (yyyyMMddhhmmss). "
                                    + e.toString());
                }
            }
        }

        if (orderKeys != null && orderKeys.length() > 0) {
            orders = new ArrayList<String>(3);
            for (StringTokenizer orderKeysTok = new StringTokenizer(orderKeys, " "); orderKeysTok
                    .hasMoreTokens();) {
                String orderKey = orderKeysTok.nextToken();
                try {
                    String justKey = orderKey;
                    if (justKey.startsWith("-") || justKey.startsWith("+"))
                        justKey = orderKey.substring(1, justKey.length());
                    OrderKeys.valueOf(justKey.replaceAll("-", "_").toUpperCase());
                    orders.add(orderKey);
                } catch (IllegalArgumentException e) {
                    throw new InvalidRequestException(
                            "One of the ordering keys isn't valid, processes can only "
                                    + "be sorted by pid, name, namespace, version, status, started and last-active "
                                    + "date." + e.toString());

                }
            }
        }
        if(limit<0) {
            throw new IllegalArgumentException("Limit should be greater or equal to 0.");
        }
        this.limit = limit;
    }

    public InstanceFilter(String filter) {
        this(filter, null, Integer.MAX_VALUE);
    }

    private Date parseDateExpression(String date) throws ParseException {
        if( date.toLowerCase().startsWith("-")  && date.length() > 1 ) {
            return RelativeDateParser.parseRelativeDate(date.substring(1));
        } else {
            return ISO8601DateParser.parse(date);
        }
    }

    /**
     * Converts the status filter value as given by a filter ('active',
     * 'suspended', ...) to an instance state as defined in the ProcessState
     * class.
     *
     * @return one of the STATE_XX constant in ProcessState
     */
    public List<Short> convertFilterState() {
        List<Short> result = new ArrayList<Short>(5);
        short noState = 200;
        for (String status : statusFilter) {
            if (StatusKeys.ACTIVE.toString().equalsIgnoreCase(status)) {
                result.add(ProcessState.STATE_NEW);
                result.add(ProcessState.STATE_ACTIVE);
                result.add(ProcessState.STATE_READY);
            } else if (StatusKeys.SUSPENDED.toString().equalsIgnoreCase(status)) {
                result.add(ProcessState.STATE_SUSPENDED);
            } else if (StatusKeys.ERROR.toString().equalsIgnoreCase(status)) {
                result.add(noState); // Error instance state doesn't exist yet
            } else if (StatusKeys.COMPLETED.toString().equalsIgnoreCase(status)) {
                result.add(ProcessState.STATE_COMPLETED_OK);
            } else if (StatusKeys.TERMINATED.toString().equalsIgnoreCase(status)) {
                result.add(ProcessState.STATE_TERMINATED);
            } else if (StatusKeys.FAILED.toString().equalsIgnoreCase(status)) {
                result.add(ProcessState.STATE_COMPLETED_WITH_FAULT);
            } else {
                result.add(noState); // Non existent state
            }
        }
        return result;
    }

    public String getNameFilter() {
        return nameFilter;
    }

    public String getNamespaceFilter() {
        return namespaceFilter;
    }

    public List<String> getStatusFilter() {
        return statusFilter;
    }

    public List<String> getStartedDateFilter() {
        return startedDateFilter;
    }

    public List<String> getLastActiveDateFilter() {
        return lastActiveDateFilter;
    }

    public Map<String, String> getPropertyValuesFilter() {
        return propertyValuesFilter;
    }

    public List<String> getOrders() {
        return orders;
    }

    public List<String> getPidFilter() {
        return pids;
    }

    public boolean arePidsNegative() {
        return arePidsNegative;
    }

    public List<String> getIidFilter() {
        return iids;
    }

    public static void main(String[] args) {
        InstanceFilter instf = new InstanceFilter(
                "name = dtc* namespace=http://www.intalio.com* "
                        + "status=active|terminated started>=2005-11-29T15:15:19 started<2005-11-29T15:15:20 last-active < 2005-11-30 "
                        + "${http://ode.org/}order-id= 12 $shipping-id=aa45fz", "name started", 50);
        System.out.println(instf);
    }

    @Override
    protected Criteria parseKey(String keyVal) {
        if (keyVal.startsWith("$")) return Criteria.PROPERTY;
        else return Criteria.valueOf(keyVal);
    }

    @Override
    protected Criteria[] getFilterKeys() {
        return Criteria.values();
    }

    @Override
    protected void process(Criteria key, Restriction<String> rest) {
        key.process(this, rest.originalKey, rest.op, rest.value);
    }

    /**
     * @return the limit
     */
    public int getLimit() {
        return limit;
    }


    public String toString() {
        StringBuffer buf = new StringBuffer();
        buf.append("InstanceFilter {");
        buf.append("iids="+iids);
        if( !arePidsNegative ) {
            buf.append(",pids="+pids);
        } else {
            buf.append(",-pids="+pids);
        }
        buf.append(",name="+nameFilter);
        buf.append(",namespace="+namespaceFilter);
        buf.append(",status="+statusFilter);
        buf.append(",startedDate="+startedDateFilter);
        buf.append(",lastActiveDate="+lastActiveDateFilter);
        buf.append(",propertyValues="+propertyValuesFilter);
        buf.append(",orders="+orders);
        buf.append(",limit="+limit);
        buf.append("}");
        return buf.toString();
    }

    private static List<String> parse(String pipeDelimited) {
        List<String> list = new ArrayList<String>();
        StringTokenizer tok = new StringTokenizer(pipeDelimited, "|");
        while (tok.hasMoreTokens()) {
            list.add(tok.nextToken());
        }
        return list;
    }
}
