/*
 * Copyright 2009-2010 by The Regents of the University of California
 * Licensed 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 from
 * 
 *     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 edu.uci.ics.hyracks.algebricks.core.algebra.properties;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;

import edu.uci.ics.hyracks.algebricks.common.utils.ListSet;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.EquivalenceClass;
import edu.uci.ics.hyracks.algebricks.core.algebra.base.LogicalVariable;
import edu.uci.ics.hyracks.algebricks.core.algebra.properties.ILocalStructuralProperty.PropertyType;

public class PropertiesUtil {

    public Set<LogicalVariable> closureUnderFDs(Collection<LogicalVariable> vars, List<FunctionalDependency> fdList) {
        Set<LogicalVariable> k = new ListSet<LogicalVariable>(vars);
        boolean change;
        do {
            change = false;
            for (FunctionalDependency fd : fdList) {
                List<LogicalVariable> h = fd.getHead();
                if (k.containsAll(h)) {
                    List<LogicalVariable> t = fd.getTail();
                    for (LogicalVariable v : t) {
                        if (!(k.contains(v))) {
                            k.add(v);
                            change = true;
                        }
                    }
                }
            }
        } while (change);
        return k;
    }

    public static boolean matchLocalProperties(List<ILocalStructuralProperty> reqd,
            List<ILocalStructuralProperty> dlvd, Map<LogicalVariable, EquivalenceClass> equivalenceClasses,
            List<FunctionalDependency> fds) {
        if (reqd == null) {
            return true;
        }
        if (dlvd == null) {
            return false;
        }
        normalizeLocals(reqd, equivalenceClasses, fds);
        normalizeLocals(dlvd, equivalenceClasses, fds);

        ListIterator<ILocalStructuralProperty> dlvdIter = dlvd.listIterator();

        Set<LogicalVariable> rqdCols = new ListSet<LogicalVariable>();
        Set<LogicalVariable> dlvdCols = new ListSet<LogicalVariable>();
        for (ILocalStructuralProperty r : reqd) {
            if (r.getPropertyType() == PropertyType.LOCAL_GROUPING_PROPERTY) {
                rqdCols.clear();
                r.getVariables(rqdCols);
            }
            boolean implied = false;
            while (!implied && dlvdIter.hasNext()) {
                ILocalStructuralProperty d = dlvdIter.next();
                switch (r.getPropertyType()) {
                    case LOCAL_ORDER_PROPERTY: {
                        if (d.getPropertyType() != PropertyType.LOCAL_ORDER_PROPERTY) {
                            return false;
                        }
                        LocalOrderProperty lop = (LocalOrderProperty) d;
                        if (lop.getColumn() == ((LocalOrderProperty) r).getColumn()
                                && lop.getOrder() == ((LocalOrderProperty) r).getOrder()) {
                            implied = true;
                        } else {
                            return false;
                        }
                        break;
                    }
                    case LOCAL_GROUPING_PROPERTY: {
                        dlvdCols.clear();
                        d.getColumns(dlvdCols);
                        for (LogicalVariable v : dlvdCols) {
                            if (rqdCols.contains(v)) {
                                rqdCols.remove(v);
                            } else {
                                return false;
                            }
                        }
                        if (rqdCols.isEmpty()) {
                            implied = true;
                        }
                        break;
                    }
                    default: {
                        throw new IllegalStateException();
                    }
                }
            }
            if (!implied) {
                return false;
            }
        }
        return true;

    }

    public static boolean matchPartitioningProps(IPartitioningProperty reqd, IPartitioningProperty dlvd,
            boolean mayExpandProperties) {

        INodeDomain dom1 = reqd.getNodeDomain();
        INodeDomain dom2 = dlvd.getNodeDomain();
        if (dom1 != null && dom2 != null && !dom1.sameAs(dom2)) {
            return false;
        }

        switch (reqd.getPartitioningType()) {
            case RANDOM: {
                // anything matches RANDOM
                return true;
            }
            case UNORDERED_PARTITIONED: {
                switch (dlvd.getPartitioningType()) {
                    case UNORDERED_PARTITIONED: {
                        UnorderedPartitionedProperty ur = (UnorderedPartitionedProperty) reqd;
                        UnorderedPartitionedProperty ud = (UnorderedPartitionedProperty) dlvd;
                        if (mayExpandProperties) {
                            return ur.getColumnSet().containsAll(ud.getColumnSet());
                        } else {
                            return ur.getColumnSet().equals(ud.getColumnSet());
                        }
                    }
                    case ORDERED_PARTITIONED: {
                        UnorderedPartitionedProperty ur = (UnorderedPartitionedProperty) reqd;
                        OrderedPartitionedProperty od = (OrderedPartitionedProperty) dlvd;
                        if (mayExpandProperties) {
                            return ur.getColumnSet().containsAll(od.getOrderColumns());
                        } else {
                            return ur.getColumnSet().containsAll(od.getOrderColumns())
                                    && od.getOrderColumns().containsAll(ur.getColumnSet());
                        }
                    }
                    default: {
                        return false;
                    }
                }
            }
            case ORDERED_PARTITIONED: {
                switch (dlvd.getPartitioningType()) {
                    case ORDERED_PARTITIONED: {
                        OrderedPartitionedProperty or = (OrderedPartitionedProperty) reqd;
                        OrderedPartitionedProperty od = (OrderedPartitionedProperty) dlvd;
                        if (mayExpandProperties) {
                            return isPrefixOf(od.getOrderColumns(), or.getOrderColumns());
                        } else {
                            return od.getOrderColumns().equals(or.getOrderColumns());
                        }
                    }
                    default: {
                        return false;
                    }
                }
            }
            default: {
                return (dlvd.getPartitioningType() == reqd.getPartitioningType());
            }
        }
    }

    /**
     * @param pref
     * @param target
     * @return true iff pref is a prefix of target
     */
    private static boolean isPrefixOf(List<OrderColumn> pref, List<OrderColumn> target) {
        Iterator<OrderColumn> iter = target.iterator();
        for (OrderColumn v : pref) {
            if (!iter.hasNext()) {
                return false;
            }
            if (!v.equals(iter.next())) {
                return false;
            }
        }
        return true;
    }

    public static ArrayList<OrderColumn> applyFDsToOrderColumns(ArrayList<OrderColumn> orderColumns,
            List<FunctionalDependency> fds) {
        // the set of vars. is ordered
        // so we try the variables in order from last to first
        if (fds == null || fds.isEmpty()) {
            return orderColumns;
        }

        int deleted = 0;
        for (int i = orderColumns.size() - 1; i >= 0; i--) {
            for (FunctionalDependency fdep : fds) {
                if (impliedByPrefix(orderColumns, i, fdep)) {
                    orderColumns.set(i, null);
                    deleted++;
                    break;
                }
            }
        }
        ArrayList<OrderColumn> norm = new ArrayList<OrderColumn>(orderColumns.size() - deleted);
        for (OrderColumn oc : orderColumns) {
            if (oc != null) {
                norm.add(oc);
            }
        }
        return norm;
    }

    public static ArrayList<OrderColumn> replaceOrderColumnsByEqClasses(ArrayList<OrderColumn> orderColumns,
            Map<LogicalVariable, EquivalenceClass> equivalenceClasses) {
        if (equivalenceClasses == null || equivalenceClasses.isEmpty()) {
            return orderColumns;
        }
        ArrayList<OrderColumn> norm = new ArrayList<OrderColumn>();
        for (OrderColumn v : orderColumns) {
            EquivalenceClass ec = equivalenceClasses.get(v.getColumn());
            if (ec == null) {
                norm.add(v);
            } else {
                if (ec.representativeIsConst()) {
                    // trivially satisfied, so the var. can be removed
                } else {
                    norm.add(new OrderColumn(ec.getVariableRepresentative(), v.getOrder()));
                }
            }
        }
        return norm;
    }

    private static boolean impliedByPrefix(ArrayList<OrderColumn> vars, int i, FunctionalDependency fdep) {
        if (!fdep.getTail().contains(vars.get(i).getColumn())) {
            return false;
        }
        boolean fdSat = true;
        for (LogicalVariable pv : fdep.getHead()) {
            boolean isInPrefix = false;
            for (int j = 0; j < i; j++) {
                if (vars.get(j).getColumn().equals(pv)) {
                    isInPrefix = true;
                    break;
                }
            }
            if (!isInPrefix) {
                fdSat = false;
                break;
            }
        }
        return fdSat;
    }

    private static void normalizeLocals(List<ILocalStructuralProperty> props,
            Map<LogicalVariable, EquivalenceClass> equivalenceClasses, List<FunctionalDependency> fds) {
        ListIterator<ILocalStructuralProperty> propIter = props.listIterator();
        int pos = -1;
        while (propIter.hasNext()) {
            ILocalStructuralProperty p = propIter.next();
            if (p.getPropertyType() == PropertyType.LOCAL_GROUPING_PROPERTY) {
                ((LocalGroupingProperty) p).normalizeGroupingColumns(equivalenceClasses, fds);
                pos++;
            } else {
                LocalOrderProperty ord = (LocalOrderProperty) p;
                EquivalenceClass ec = equivalenceClasses.get(ord.getColumn());
                if (ec != null) {
                    if (ec.representativeIsConst()) {
                        propIter.remove();
                    } else {
                        ord.getOrderColumn().setColumn(ec.getVariableRepresentative());
                        pos++;
                    }
                } else {
                    pos++;
                }
            }
        }

        if (pos < 1) {
            return;
        }

        while (propIter.hasPrevious()) {
            ILocalStructuralProperty p = propIter.previous();
            ListIterator<ILocalStructuralProperty> secondIter = props.listIterator(pos);
            pos--;
            Set<LogicalVariable> cols = new ListSet<LogicalVariable>();
            while (secondIter.hasPrevious()) {
                secondIter.previous().getColumns(cols);
            }
            secondIter = null;
            for (FunctionalDependency fdep : fds) {
                LinkedList<LogicalVariable> columnsOfP = new LinkedList<LogicalVariable>();
                p.getColumns(columnsOfP);
                if (impliedByPrefix(columnsOfP, cols, fdep)) {
                    propIter.remove();
                    break;
                }
            }
        }
    }

    private static boolean impliedByPrefix(List<LogicalVariable> colsOfProp, Set<LogicalVariable> colsOfPrefix,
            FunctionalDependency fdep) {
        return fdep.getTail().containsAll(colsOfProp) && colsOfPrefix.containsAll(fdep.getHead());
    }
}
