/*
 * 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.geode.cache.query.internal;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.logging.log4j.Logger;

import org.apache.geode.cache.CacheClosedException;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.query.AmbiguousNameException;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryExecutionTimeoutException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.RegionNotFoundException;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.parse.OQLLexerTokenTypes;
import org.apache.geode.cache.query.internal.types.TypeUtils;
import org.apache.geode.cache.query.types.CollectionType;
import org.apache.geode.cache.query.types.MapType;
import org.apache.geode.cache.query.types.ObjectType;
import org.apache.geode.logging.internal.log4j.api.LogService;
import org.apache.geode.security.NotAuthorizedException;

public class CompiledIteratorDef extends AbstractCompiledValue {
  private static final Logger logger = LogService.getLogger();

  private String name;
  private ObjectType elementType;
  private CompiledValue collectionExpr;

  /**
   * Creates a new instance of CompiledIteratorDef name and type can be null
   */
  public CompiledIteratorDef(String name, ObjectType elementType, CompiledValue collectionExpr) {
    this.name = name;
    this.elementType = elementType == null ? TypeUtils.OBJECT_TYPE : elementType;
    this.collectionExpr = collectionExpr;
  }

  @Override
  public List getChildren() {
    return Collections.singletonList(collectionExpr);
  }

  /**
   * Returns a RuntimeIterator (or null if evaluates to null or UNDEFINED); the collection expr is
   * evaluated lazily after dependencies are known
   */
  @Override
  public Object evaluate(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    throw new UnsupportedOperationException(
        "Not to be evaluated directly");
  }

  public RuntimeIterator getRuntimeIterator(ExecutionContext context)
      throws TypeMismatchException, AmbiguousNameException, NameResolutionException {
    RuntimeIterator rIter = null;
    // check cached in context
    rIter = (RuntimeIterator) context.cacheGet(this);
    if (rIter != null) {
      return rIter;
    }
    ObjectType type = this.elementType;
    if (type.equals(TypeUtils.OBJECT_TYPE)) {
      // check to see if there's a typecast for this collection
      ObjectType typc = getCollectionElementTypeCast();
      if (typc != null) {
        type = typc;
      } else {
        // Try to determine better type
        // Now only works for CompiledPaths
        // Does not determine type of nested query
        if (!(this.collectionExpr instanceof CompiledSelect)) {
          type = computeElementType(context);
        }
      }
    }
    rIter = new RuntimeIterator(this, type);
    // generate from clause should take care of bucket region substitution if
    // necessary and then set the definition.
    String fromClause = genFromClause(context);
    rIter.setDefinition(fromClause);
    /*
     * If the type of RunTimeIterator is still ObjectType & if the RuneTimeIterator is independent
     * of any iterator of the scopes less than or equal to its own scope, we can evaluate the
     * collection via RuntimeIterator. This will initialize the Collection of RuntimeIterator ,
     * which is OK. The code in RuntimeIterator will be rectified such that the ElementType of that
     * RuntimeIterator is taken from the collection
     */
    if (type.equals(TypeUtils.OBJECT_TYPE)
        && !this.isDependentOnAnyIteratorOfScopeLessThanItsOwn(context)) {
      // The current Iterator definition is independent , so lets evaluate
      // the collection
      evaluateCollectionForIndependentIterator(context, rIter);
    }
    // cache in context
    context.cachePut(this, rIter);
    return rIter;
  }

  protected void evaluateCollectionForIndependentIterator(ExecutionContext context,
      RuntimeIterator rIter)
      throws RegionNotFoundException, TypeMismatchException {
    try {
      rIter.evaluateCollection(context);
    } catch (QueryExecutionTimeoutException qet) {
      throw qet;
    } catch (RegionNotFoundException re) {
      throw re;
    } catch (NotAuthorizedException e) {
      throw e;
    } catch (QueryExecutionCanceledException e) {
      throw e;
    } catch (CacheClosedException e) {
      throw e;
    } catch (Exception e) {
      if (logger.isDebugEnabled()) {
        logger.debug("Exception while getting runtime iterator.", e);
      }
      throw new TypeMismatchException(
          "Exception in evaluating the Collection Expression in getRuntimeIterator() even though the Collection is independent of any RuntimeIterator",
          e);
    }
  }

  ObjectType getCollectionElementTypeCast() throws TypeMismatchException {
    ObjectType typ = this.collectionExpr.getTypecast();
    if (typ != null) {
      if (!(typ instanceof CollectionType)) {
        throw new TypeMismatchException(
            String.format("An iterator definition must be a collection type, not a %s",
                typ));
      }
      if (typ instanceof MapType) { // we iterate over map entries
        return ((MapType) typ).getEntryType();
      }
      return ((CollectionType) typ).getElementType();
    }
    return null;
  }

  /** Evaluate just the collectionExpr */
  SelectResults evaluateCollection(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    return evaluateCollection(context, null);
  }

  /**
   * Evaluate just the collectionExpr
   *
   * @param stopAtIter the RuntimeIterator associated with this iterator defn -- don't use this or
   *        any subsequent runtime iterators to evaluate.
   */
  SelectResults evaluateCollection(ExecutionContext context, RuntimeIterator stopAtIter)
      throws FunctionDomainException, TypeMismatchException, NameResolutionException,
      QueryInvocationTargetException {
    Object coll;

    context.currentScope().setLimit(stopAtIter);
    try {
      coll = this.collectionExpr.evaluate(context);
    } finally {
      context.currentScope().setLimit(null);
    }
    // if we don't have an elementType and there's a typecast, apply the
    // element type here
    if (TypeUtils.OBJECT_TYPE.equals(this.elementType)) {
      ObjectType elmTypc = getCollectionElementTypeCast();
      if (elmTypc != null) {
        this.elementType = elmTypc;
      }
    }

    // PR bucketRegion substitution should have already happened
    // at the expression evaluation level

    return prepareIteratorDef(coll, this.elementType, context);
  }

  @Override
  public int getType() {
    return OQLLexerTokenTypes.ITERATOR_DEF;
  }

  // for test purposes...
  public String getName() {
    return this.name;
  }

  public ObjectType getElementType() {
    return this.elementType;
  }

  public CompiledValue getCollectionExpr() {
    return this.collectionExpr;
  }

  public void setCollectionExpr(CompiledValue collectionExpr) {
    this.collectionExpr = collectionExpr;
  }

  /**
   * TODO: We need to implement the below method of computeDependencies Once we come to implement
   * changes for partitioned region querying, as in that case if first iterator itself is a Select
   * Query , then ideally we cannot call that CompiledIteratorDef independent ( which will be the
   * case at present). When we use this commented function we will also need to take care of
   * correctly implementing the function isDependentOnCurrentScope etc functions.
   */
  @Override
  public Set computeDependencies(ExecutionContext context)
      throws TypeMismatchException, AmbiguousNameException, NameResolutionException {
    return context.addDependencies(this, this.collectionExpr.computeDependencies(context));
  }

  // TODO: this method is overly complex, duplicating logic already
  // in query evaluation itself. It is overly complex ==> It will not be
  // necessary once we have full typing support.
  // There is a limitation here that it assumes that the collectionExpr is some
  // path on either a RuntimeIterator or a Region.
  private ObjectType computeElementType(ExecutionContext context) throws AmbiguousNameException {
    ObjectType type = PathUtils.computeElementTypeOfExpression(context, this.collectionExpr);
    // if it's a Map, we want the Entry type, not the value type
    if (type.isMapType()) {
      return ((MapType) type).getEntryType();
    }
    if (type.isCollectionType()) { // includes Regions and arrays
      return ((CollectionType) type).getElementType();
    }
    return type;
  }

  /**
   * Convert the given object to a SelectResults. Must be a collection of some sort. The obj passed
   * in must be unmodified, but the resulting SelectResults may or may not be modifiable. Return
   * null if obj is null or UNDEFINED.
   */
  private SelectResults prepareIteratorDef(Object obj, ObjectType elementType,
      ExecutionContext context) throws TypeMismatchException {
    if (obj == null) {
      return null;
    }
    if (obj == QueryService.UNDEFINED) {
      return null;
    }
    if (obj instanceof SelectResults) {
      // probably came from nested query or is a QRegion already from region
      // path
      SelectResults sr = (SelectResults) obj;
      // override the elementType if not Object.class (does not apply to
      // StructBags)
      if (!elementType.equals(TypeUtils.OBJECT_TYPE)) {
        sr.setElementType(elementType);
      }
      return sr;
    }
    if (obj instanceof Region) {
      // this can happen if region passed in as parameter
      QRegion qRegion = new QRegion((Region) obj, false, context);
      if (!elementType.equals(TypeUtils.OBJECT_TYPE)) {
        // override the valueConstraint, if any
        qRegion.setElementType(elementType);
      }
      return qRegion;
    }
    // if this is a domain collection, it should be unmodifiable
    // if obj is a Collection but not a SelectResults, it must be from the
    // domain, otherwise it would be a SelectResults.
    if (obj instanceof Collection) {
      // do not lose ordering and duplicate information,
      ResultsCollectionWrapper res = new ResultsCollectionWrapper(elementType, (Collection) obj);
      res.setModifiable(false);
      return res;
    }
    // Object[] is wrapped and considered a domain object so unmodifiable
    if (obj instanceof Object[]) {
      // the element type is specified in the array itself, unless we have
      // something more specific
      if (elementType.equals(TypeUtils.OBJECT_TYPE)) { // if we don't have
        // constraint info
        elementType = TypeUtils.getObjectType(obj.getClass().getComponentType());
      }
      // do not lose ordering and duplicate information,
      ResultsCollectionWrapper res =
          new ResultsCollectionWrapper(elementType, Arrays.asList((Object[]) obj));
      res.setModifiable(false);
      return res;
    }
    // TODO: primitive arrays?
    if (obj instanceof Map) {
      if (elementType.equals(TypeUtils.OBJECT_TYPE)) { // if we don't have more
        // specific type info,
        // use Map.Entry
        elementType = TypeUtils.getObjectType(Map.Entry.class);
      }
      ResultsCollectionWrapper res =
          new ResultsCollectionWrapper(elementType, ((Map) obj).entrySet());
      res.setModifiable(false);
      return res;
    } else {
      obj = new Object[] {obj};
      // the element type is specified in the array itself, unless we have
      // something more specific
      if (elementType.equals(TypeUtils.OBJECT_TYPE)) { // if we don't have
        // constraint info
        elementType = TypeUtils.getObjectType(obj.getClass().getComponentType());
      }
      // do not lose ordering and duplicate information,
      ResultsCollectionWrapper res =
          new ResultsCollectionWrapper(elementType, Arrays.asList((Object[]) obj));
      res.setModifiable(false);
      return res;
    }
  }

  String genFromClause(ExecutionContext context)
      throws AmbiguousNameException, TypeMismatchException, NameResolutionException {
    StringBuilder sbuff = new StringBuilder();
    collectionExpr.generateCanonicalizedExpression(sbuff, context);
    return sbuff.toString();
  }

  /**
   * Checks if the iterator in question is dependent on any other RuntimeIterator of its own or
   * lesser scope.
   */
  boolean isDependentOnAnyIteratorOfScopeLessThanItsOwn(ExecutionContext context) {
    // Get the list of all iterators on which the colelction expression
    // is ultimately dependent on

    // If dependent on self then also assume it to be dependent
    boolean isDep = false;
    // Get the list of all iterators on which the colelction expression
    // is dependent on
    Set dependencySet = context.getDependencySet(this, true);
    Iterator itr = dependencySet.iterator();
    int currScope = context.currentScope().getScopeID();// context.getScopeCount();
    while (itr.hasNext()) {
      RuntimeIterator ritr = (RuntimeIterator) itr.next();
      if (ritr.getScopeID() <= currScope) {
        isDep = true;
        break;
      }
    }
    return isDep;
  }
}
