package org.apache.rya.indexing.external.tupleSet;

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



import info.aduna.iteration.CloseableIteration;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.openrdf.query.BindingSet;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.algebra.Projection;
import org.openrdf.query.algebra.TupleExpr;
import org.openrdf.query.algebra.Var;
import org.openrdf.query.algebra.evaluation.impl.ExternalSet;
import org.openrdf.query.algebra.helpers.QueryModelVisitorBase;

import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * This is an abstract class of delegating the evaluation of part
 * of a SPARQL query to an external source.  The {@link TupleExpr} returned by {@link ExternalTupleSet#getTupleExpr()}
 * represents the SPARQL string that this node evaluates, and table returned by {@link ExternalTupleSet#getTableVarMap()}
 * maps the variables of TupleExpr to the variables stored in the external store (which may be different).  The map
 * returned by {@link ExternalTupleSet#getSupportedVariableOrderMap()} provides a map of all the variable orders in which
 * data is written to the supporting, and is useful for determining which {@link BindingSet} can be passed into
 * {@link ExternalTupleSet#evaluate(BindingSet)}.
 *
 */
public abstract class ExternalTupleSet extends ExternalSet {

	public static final String VAR_ORDER_DELIM = ";";
	public static final String CONST_PREFIX = "-const-";
	public static final String VALUE_DELIM = "\u0000";
	private Projection tupleExpr;
    private Map<String, String> tableVarMap = Maps.newHashMap();  //maps vars in tupleExpr to var in stored binding sets
    private Map<String, Set<String>> supportedVarOrders = Maps.newHashMap(); //indicates supported var orders
    private Map<String, org.openrdf.model.Value> valMap;

    public ExternalTupleSet() {
    }

    public ExternalTupleSet(Projection tupleExpr) {
    	Preconditions.checkNotNull(tupleExpr);
        this.tupleExpr = tupleExpr;
        valMap = getValMap();
        updateTableVarMap(tupleExpr, tupleExpr);
    }

    @Override
    abstract public CloseableIteration<BindingSet, QueryEvaluationException> evaluate(BindingSet bindings) throws QueryEvaluationException;

    @Override
    public Set<String> getBindingNames() {
        return tupleExpr.getBindingNames();
    }

    @Override
    public Set<String> getAssuredBindingNames() {
        return tupleExpr.getAssuredBindingNames();
    }

    @Override
    public String getSignature() {
        return "(External Projection) " + Joiner.on(", ").join(tupleExpr.getProjectionElemList().getElements()).replaceAll("\\s+", " ");
    }

    public Projection getTupleExpr() {
        return tupleExpr;
    }

    public void setProjectionExpr(Projection tupleExpr) {
    	Preconditions.checkNotNull(tupleExpr);
    	if(this.tupleExpr == null) {
    		updateTableVarMap(tupleExpr, tupleExpr);
    	} else {
    		updateTableVarMap(tupleExpr, this.tupleExpr);
    	}
        this.tupleExpr = tupleExpr;
        valMap = getValMap();
		if (supportedVarOrders.size() != 0) {
			updateSupportedVarOrderMap();
		}
    }

    public void setTableVarMap(Map<String,String> vars) {
    	Preconditions.checkNotNull(vars);
        this.tableVarMap = vars;
    }

    public Map<String, String> getTableVarMap() {
        return this.tableVarMap;
    }

    public void setSupportedVariableOrderMap(Map<String, Set<String>> varOrders) {
    	Preconditions.checkNotNull(varOrders);
        this.supportedVarOrders = varOrders;
    }

    public void setSupportedVariableOrderMap(List<String> varOrders) {
    	Preconditions.checkNotNull(varOrders);
    	this.supportedVarOrders = createSupportedVarOrderMap(varOrders);
    }

    public Map<String, Set<String>> getSupportedVariableOrderMap() {
        return supportedVarOrders;
    }

    public Map<String, org.openrdf.model.Value> getConstantValueMap() {
    	return valMap;
    }

    @Override
    public ExternalSet clone() {
        final ExternalTupleSet clone = (ExternalTupleSet) super.clone();
        clone.setProjectionExpr(this.tupleExpr.clone());
        clone.tableVarMap = Maps.newHashMap();
        for(final String s: this.tableVarMap.keySet()) {
            clone.tableVarMap.put(s,this.tableVarMap.get(s));
        }
        clone.supportedVarOrders = Maps.newHashMap();
        for(final String s: this.supportedVarOrders.keySet()) {
            clone.supportedVarOrders.put(s,this.supportedVarOrders.get(s));
        }
        return clone;
    }

	public Map<String, Set<String>> getSupportedVariableOrders() {
		return supportedVarOrders;
	}

	public boolean supportsBindingSet(Set<String> bindingNames) {
		final Collection<Set<String>> values = supportedVarOrders.values();
		final Set<String> bNames = Sets.newHashSet();
		final Set<String> bNamesWithConstants = Sets.newHashSet();

		for (final String s : this.getTupleExpr().getBindingNames()) {
			if (bindingNames.contains(s)) {
				bNames.add(s);
				bNamesWithConstants.add(s);
			} else if(s.startsWith(CONST_PREFIX)) {
				bNamesWithConstants.add(s);
			}
		}
		return values.contains(bNames) || values.contains(bNamesWithConstants);
	}

	/**
	 * @param tupleMatch
	 *            - project expression - call after setting {@link tupleExpr} to
	 *            map new variables to old -- the variables in the binding list
	 *            of the new tupleExpr (tupleMatch) must map to the
	 *            corresponding variables in the binding list of the old
	 *            tupleExpr
	 */
	private void updateTableVarMap(TupleExpr newTuple, TupleExpr oldTuple) {

		final List<String> replacementVars = Lists.newArrayList(newTuple
				.getBindingNames());
		final List<String> tableVars = Lists.newArrayList(oldTuple
				.getBindingNames());

		final Map<String, String> tableMap = Maps.newHashMap();

		for (int i = 0; i < tableVars.size(); i++) {
			tableMap.put(replacementVars.get(i), tableVars.get(i));
		}
		this.setTableVarMap(tableMap);
	}

	/**
	 * call after setting {@link tableVarMap} to update map of supported
	 * variables in terms of variables in new tupleExpr
	 */
	private void updateSupportedVarOrderMap() {

		Preconditions.checkArgument(supportedVarOrders.size() != 0);;
		final Map<String, Set<String>> newSupportedOrders = Maps.newHashMap();
		final BiMap<String, String> biMap = HashBiMap.create(tableVarMap)
				.inverse();
		Set<String> temp = null;
		final Set<String> keys = supportedVarOrders.keySet();

		for (final String s : keys) {
			temp = supportedVarOrders.get(s);
			final Set<String> newSet = Sets.newHashSet();

			for (final String t : temp) {
				newSet.add(biMap.get(t));
			}

			final String[] tempStrings = s.split(VAR_ORDER_DELIM);
			String v = "";
			for (final String u : tempStrings) {
				if (v.length() == 0) {
					v = v + biMap.get(u);
				} else {
					v = v + VAR_ORDER_DELIM + biMap.get(u);
				}
			}
			newSupportedOrders.put(v, newSet);
		}
		supportedVarOrders = newSupportedOrders;
	}

	 /**
    *
    * @param orders
    * @return - map with all possible orders in which results are written to the table
    */
   private Map<String, Set<String>> createSupportedVarOrderMap(List<String> orders) {
	   final Map<String, Set<String>> supportedVars = Maps.newHashMap();

       for (final String t : orders) {
           final String[] tempOrder = t.split(VAR_ORDER_DELIM);
           final Set<String> varSet = Sets.newHashSet();
           String u = "";
           for (final String s : tempOrder) {
               if(u.length() == 0) {
                   u = s;
               } else{
                   u = u+ VAR_ORDER_DELIM + s;
               }
               varSet.add(s);
               supportedVars.put(u, new HashSet<String>(varSet));
           }
       }
       return supportedVars;
   }

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof ExternalTupleSet)) {
            return false;
        } else {
            final ExternalTupleSet arg = (ExternalTupleSet) other;
            if (this.getTupleExpr().equals(arg.getTupleExpr())) {
                return true;
            } else {
                return false;
            }
        }
    }

    @Override
    public int hashCode() {
        int result = 17;
        result = 31*result + tupleExpr.hashCode();
        return result;
    }

    private Map<String, org.openrdf.model.Value> getValMap() {
		ValueMapVisitor valMapVis = new ValueMapVisitor();
		tupleExpr.visit(valMapVis);
		return valMapVis.getValMap();
	}


	/**
	 *
	 * Extracts the values associated with constant labels in the query Used to
	 * create binding sets from range scan
	 */
	private class ValueMapVisitor extends
			QueryModelVisitorBase<RuntimeException> {
		Map<String, org.openrdf.model.Value> valMap = Maps.newHashMap();

		public Map<String, org.openrdf.model.Value> getValMap() {
			return valMap;
		}

		@Override
		public void meet(Var node) {
			if (node.getName().startsWith("-const-")) {
				valMap.put(node.getName(), node.getValue());
			}
		}
	}


}
