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

import java.sql.Timestamp;
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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.common.BpelEventFilter;
import org.apache.ode.bpel.common.Filter;
import org.apache.ode.bpel.common.InstanceFilter;
import org.apache.ode.utils.ISO8601DateParser;
import org.apache.ode.utils.RelativeDateParser;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;

/**
 * Class used for converting "filter" objects into Hibernate
 * {@link org.hibernate.Criteria} objects.
 */
class CriteriaBuilder {
    static final Logger __log = LoggerFactory.getLogger(CriteriaBuilder.class);

    /**
     * Build a HQL query from an instance filter.
     * @param filter filter
     */
    Query buildHQLQuery(Session session, InstanceFilter filter) {
        Map<String, Object> parameters = new HashMap<String, Object>();

        StringBuffer query = new StringBuffer();

        query.append("select pi from HProcessInstance as pi left join fetch pi.fault ");

        if (filter != null) {
            // Building each clause
            ArrayList<String> clauses = new ArrayList<String>();

            // iid filter
            if ( filter.getIidFilter() != null ) {
                StringBuffer filters = new StringBuffer();
                List<String> iids = filter.getIidFilter();
                for (int m = 0; m < iids.size(); m++) {
                    filters.append(" pi.id = :iid").append(m);
                    parameters.put("iid" + m, Long.parseLong(iids.get(m)));
                    if (m < iids.size() - 1) filters.append(" or");
                }
                clauses.add(" (" + filters + ")");
            }

            // pid filter
            if (filter.getPidFilter() != null) {
                StringBuffer filters = new StringBuffer();
                List<String> pids = filter.getPidFilter();
                String cmp;
                if (filter.arePidsNegative()) {
                    cmp = " != ";
                } else {
                    cmp = " = ";
                }
                for (int m = 0; m < pids.size(); m++) {
                    filters.append(" pi.process.processId ").append(cmp).append(" :pid").append(m);
                    parameters.put("pid" + m, pids.get(m));
                    if (m < pids.size() - 1) filters.append(" or");
                }
                clauses.add(" (" + filters + ")");
            }

            // name filter
            if (filter.getNameFilter() != null) {
                clauses.add(" pi.process.typeName like :pname");
                parameters.put("pname", filter.getNameFilter().replaceAll("\\*", "%"));
            }

            // name space filter
            if (filter.getNamespaceFilter() != null) {
                clauses.add(" pi.process.typeNamespace like :pnamespace");
                parameters.put("pnamespace", filter.getNamespaceFilter().replaceAll("\\*", "%"));
            }

            // started filter
            if (filter.getStartedDateFilter() != null) {
                for ( String ds : filter.getStartedDateFilter() ) {
                    // named parameters not needed as date is parsed and is hence not
                    // prone to HQL injections
                    clauses.add(" pi.created " + dateFilter(ds));
                }
            }

            // last-active filter
            if (filter.getLastActiveDateFilter() != null) {
                for ( String ds : filter.getLastActiveDateFilter() ) {
                    // named parameters not needed as date is parsed and is hence not
                    // prone to HQL injections
                    clauses.add(" pi.lastActiveTime " + dateFilter(ds));
                }
            }

            // status filter
            if (filter.getStatusFilter() != null) {
                StringBuffer filters = new StringBuffer();
                List<Short> states = filter.convertFilterState();
                for (int m = 0; m < states.size(); m++) {
                    filters.append(" pi.state = :pstate").append(m);
                    parameters.put("pstate" + m, states.get(m));
                    if (m < states.size() - 1) filters.append(" or");
                }
                clauses.add(" (" + filters.toString() + ")");
            }

            // $property filter
            if (filter.getPropertyValuesFilter() != null) {
                Map<String,String> props = filter.getPropertyValuesFilter();
                // join to correlation sets
                query.append(" inner join pi.correlationSets as cs");
                int i = 0;
                for (String propKey : props.keySet()) {
                    i++;
                    // join to props for each prop
                    query.append(" inner join cs.properties as csp"+i);
                    // add clause for prop key and value

                    // spaces have to be escaped, might be better handled in InstanceFilter
                    String value = props.get(propKey).replaceAll("&#32;", " ");
                    if (propKey.startsWith("{")) {
                        String namespace = propKey.substring(1, propKey.lastIndexOf("}"));
                        clauses.add(" csp" + i + ".name = :cspname" + i +
                                " and csp" + i + ".namespace = :cspnamespace" + i +
                                " and csp" + i + ".value = :cspvalue" + i);

                        parameters.put("cspname" + i, propKey.substring(propKey.lastIndexOf("}") + 1, propKey.length()));
                        parameters.put("cspnamespace" + i, namespace);
                        parameters.put("cspvalue" + i, value);
                    } else {
                        clauses.add(" csp" + i + ".name = :cspname" + i +
                                " and csp" + i + ".value = :cspvalue" + i);

                        parameters.put("cspname" + i, propKey);
                        parameters.put("cspvalue" + i, value);
                    }
                }
            }

            // order by
            StringBuffer orderby = new StringBuffer("");
            if (filter.getOrders() != null) {
                orderby.append(" order by");
                List<String> orders = filter.getOrders();
                for (int m = 0; m < orders.size(); m++) {
                    String field = orders.get(m);
                    String ord = " asc";
                    if (field.startsWith("-")) {
                        ord = " desc";
                    }
                    String fieldName = " pi.id";
                    if (field.endsWith("name")) {
                        fieldName = " pi.process.typeName";
                    }
                    if (field.endsWith("namespace")) {
                        fieldName = " pi.process.typeNamespace";
                    }
                    if ( field.endsWith("version")) {
                        fieldName = " pi.process.version";
                    }
                    if ( field.endsWith("status")) {
                        fieldName = " pi.state";
                    }
                    if ( field.endsWith("started")) {
                        fieldName = " pi.created";
                    }
                    if ( field.endsWith("last-active")) {
                        fieldName = " pi.lastActiveTime";
                    }
                    orderby.append(fieldName + ord);
                    if (m < orders.size() - 1) orderby.append(", ");
                }

            }

            // Preparing the statement
            if (clauses.size() > 0) {
                query.append(" where");
                for (int m = 0; m < clauses.size(); m++) {
                    query.append(clauses.get(m));
                    if (m < clauses.size() - 1) query.append(" and");
                }
            }

            query.append(orderby);
        }

        if (__log.isDebugEnabled()) {
            __log.debug(query.toString());
        }

        Query q = session.createQuery(query.toString());

        for (String p : parameters.keySet()) {
            q.setParameter(p, parameters.get(p));
        }

        if (filter.getLimit() != 0) {
            q.setMaxResults(filter.getLimit());
        }

        return q;
    }

    private static String dateFilter(String filter) {
        String date = Filter.getDateWithoutOp(filter);
        String op = filter.substring(0,filter.indexOf(date));
        Date dt = null;
        try {
            dt = ISO8601DateParser.parse(date);
        } catch (ParseException e) {
            __log.error(e.getMessage(), e);
        }
        Timestamp ts = new Timestamp(dt.getTime());
        return op + " '" + ts.toString() + "'";
    }



  /**
   * Build a Hibernate {@link Criteria} from an instance filter.
   * @param crit target (destination) criteria
   * @param filter filter
   */
  void buildCriteria(Criteria crit, InstanceFilter filter) {
    Criteria processCrit = crit.createCriteria("process");

    // Filtering on PID
    List<String> pids = filter.getPidFilter();
    if (pids != null && pids.size() > 0) {
        Disjunction disj = Restrictions.disjunction();
        for (String pid: pids) {
            if( !filter.arePidsNegative() ) {
                disj.add(Restrictions.eq("processId", pid));
            } else {
                disj.add(Restrictions.ne("processId", pid));
            }
        }
        processCrit.add(disj);
    }

    List<String> iids = filter.getIidFilter();
    if (iids != null && iids.size() > 0) {
        Disjunction disj = Restrictions.disjunction();
        for (String iid: iids) {
            disj.add(Restrictions.eq("id", new Long(iid)));
        }
        crit.add(disj);
    }

    // Filtering on name and namespace
    if (filter.getNameFilter() != null) {
      processCrit.add(Restrictions.like("typeName", filter.getNameFilter().replaceAll("\\*", "%")));
    }
    if (filter.getNamespaceFilter() != null) {
      processCrit.add(Restrictions.like("typeNamespace", filter.getNamespaceFilter().replaceAll("\\*", "%")));
    }

    // Specific filter for status (using a disjunction between possible statuses)
    if (filter.getStatusFilter() != null) {
      List<Short> statuses = filter.convertFilterState();
      Disjunction disj = Restrictions.disjunction();
      for (short status : statuses) {
        disj.add(Restrictions.eq("state", status));
      }
      crit.add(disj);
    }

    // Specific filter for started and last active dates.
    if (filter.getStartedDateFilter() != null) {
      for (String sdf : filter.getStartedDateFilter()) {
        addFilterOnPrefixedDate(crit, sdf, "created");
      }
    }
    if (filter.getLastActiveDateFilter() != null) {
      for (String ladf : filter.getLastActiveDateFilter()) {
        addFilterOnPrefixedDate(crit, ladf,  "lastActiveTime");
      }
    }

    // Specific filter for correlation properties
    if (filter.getPropertyValuesFilter() != null) {
      Criteria propCrit = crit.createCriteria("correlationSets").createCriteria("properties");
      for (Map.Entry<String, String> corValue : filter.getPropertyValuesFilter().entrySet()) {
        String propName = (String)corValue.getKey();
        if (propName.startsWith("{")) {
          String namespace = propName.substring(1, propName.lastIndexOf("}"));
          propName = propName.substring(propName.lastIndexOf("}") + 1, propName.length());
          propCrit.add(Restrictions.eq("name", propName))
                  .add(Restrictions.eq("namespace", namespace))
                  .add(Restrictions.eq("value", corValue.getValue()));
        } else {
          propCrit.add(Restrictions.eq("name", corValue.getKey()))
                  .add(Restrictions.eq("value", corValue.getValue()));
        }
      }
    }

    // Ordering
    if (filter.orders != null) {
      for (String key : filter.orders) {
        boolean ascending = true;
        String orderKey = key;
        if (key.startsWith("+") || key.startsWith("-")) {
          orderKey = key.substring(1, key.length());
          if (key.startsWith("-")) ascending = false;
        }

        if ("name".equals(orderKey)) {
          if (ascending) processCrit.addOrder(Property.forName("typeName").asc());
          else processCrit.addOrder(Property.forName("typeName").desc());
        } else if ("namespace".equals(orderKey)) {
          if (ascending) processCrit.addOrder(Property.forName("typeNamespace").asc());
          else processCrit.addOrder(Property.forName("typeNamespace").desc());
        } else if ("pid".equals(orderKey)) {
          if (ascending) processCrit.addOrder(Property.forName("processId").asc());
          else processCrit.addOrder(Property.forName("processId").desc());
        } else if ("version".equals(orderKey)) {
          if (ascending) processCrit.addOrder(Property.forName("version").asc());
          else processCrit.addOrder(Property.forName("version").desc());
        } else if ("status".equals(orderKey)) {
          if (ascending) crit.addOrder(Property.forName("state").asc());
          else crit.addOrder(Property.forName("state").desc());
        } else if ("started".equals(orderKey)) {
          if (ascending) crit.addOrder(Property.forName("created").asc());
          else crit.addOrder(Property.forName("created").desc());
        } else if ("last-active".equals(orderKey)) {
          if (ascending) crit.addOrder(Property.forName("lastActiveTime").asc());
          else crit.addOrder(Property.forName("lastActiveTime").desc());
        }
      }
    }

    if (filter.getLimit() > 0) crit.setMaxResults(filter.getLimit());
  }

  /**
   * Build criteria for an event filter.
   * @param crit target criteria
   * @param efilter event filter
   */
  void buildCriteria(Criteria crit, BpelEventFilter efilter) {
    if (efilter.getTypeFilter() != null)
      crit.add(Restrictions.like("type", efilter.getTypeFilter().replace('*','%')));

    // Specific filter for started and last active dates.
    if (efilter.getTimestampFilter() != null) {
      for (Filter.Restriction<Date> sdf : efilter.getTimestampFilter()) {
        addFilterOnPrefixedDate(crit, sdf.op, sdf.value, "tstamp");
      }
    }

    if (efilter.limit > 0) crit.setMaxResults(efilter.limit);
  }

  void addScopeFilter(Criteria crit, String scopeId) {
    crit.add(Restrictions.eq("",scopeId));
  }

  static void addFilterOnPrefixedDate(Criteria crit, String prefixedDate, String dateAttribute) {
    Date realDate = null;
    try {
      realDate = parseDateExpression(getDateWithoutOp(prefixedDate));
    } catch (ParseException e) {
      // Never occurs, the deploy date format is pre-validated by the filter
    }
    addFilterOnPrefixedDate(crit,prefixedDate,realDate,dateAttribute);
  }

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

  static void addFilterOnPrefixedDate(Criteria crit, String op, Date date, String dateAttribute) {
    if (op.startsWith("=")) {
      crit.add(Restrictions.eq(dateAttribute, date));
    } else if (op.startsWith("<=")) {
      crit.add(Restrictions.le(dateAttribute, date));
    } else if (op.startsWith(">=")) {
      crit.add(Restrictions.ge(dateAttribute, date));
    } else if (op.startsWith("<")) {
      crit.add(Restrictions.lt(dateAttribute, date));
    } else if (op.startsWith(">")) {
      crit.add(Restrictions.gt(dateAttribute, date));
    }
  }

  private static String getDateWithoutOp(String ddf) {
    return Filter.getDateWithoutOp(ddf);
  }


}
