/*
 * 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.lang.reflect.Method;
import java.util.Collections;
import java.util.Set;

import org.apache.geode.annotations.Immutable;
import org.apache.geode.cache.query.FunctionDomainException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.SelectResults;
import org.apache.geode.cache.query.TypeMismatchException;
import org.apache.geode.cache.query.internal.index.IndexCreationHelper;
import org.apache.geode.cache.query.internal.types.TypeUtils;
import org.apache.geode.cache.query.types.ObjectType;
import org.apache.geode.cache.query.types.StructType;

/**
 * Value representing a current iteration element. This is the representation used during
 * evaluation.
 *
 * A RuntimeIterator can be in one of two states. If it is independent of the current context scope
 * then its collection is evaluated lazily, in which case collection is initialized and knows its
 * elementType. The elementType field is the same value as in the collection. Otherwise, collection
 * is UNINITIALIZED and the elementType is set in any case.
 *
 * A RuntimeIterator can also be named or anonymous (name is null).
 *
 */
public class RuntimeIterator extends AbstractCompiledValue {

  // token to differentiate null from uninitialized
  @Immutable
  private static final SelectResults UNINITIALIZED = new ResultsBag(0, null);
  private Object current = UNINITIALIZED;
  private final String name;
  private SelectResults collection = UNINITIALIZED;
  private final CompiledIteratorDef cmpIteratorDefn;
  /** may be more specific than that in cmpIteratorDefn */
  private ObjectType elementType;
  /** for canonicalization */
  private String internalId = null;
  private String definition = null;
  private String index_internal_id = null;
  private int scopeID = -1;

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

  public ObjectType getElementType() {
    return elementType;
  }

  RuntimeIterator(CompiledIteratorDef cmpIteratorDefn, ObjectType elementType) {
    if (elementType == null || cmpIteratorDefn == null) {
      throw new IllegalArgumentException(
          "elementType and/or cmpIteratorDefn should not be null");
    }
    this.name = cmpIteratorDefn.getName();
    this.elementType = elementType;
    this.cmpIteratorDefn = cmpIteratorDefn;
  }

  CompiledIteratorDef getCmpIteratorDefn() {
    return cmpIteratorDefn;
  }

  public String getName() {
    return name;
  }

  /**
   * (Re)evaluate in the context of the current iterations through the cross-product. If this
   * iterator is not dependent on the current iteration, then just return the previously evaluated
   * collection. Otherwise, re-evaluate. Returns null if the collection itself is null or UNDEFINED
   */
  public SelectResults evaluateCollection(ExecutionContext context) throws FunctionDomainException,
      TypeMismatchException, NameResolutionException, QueryInvocationTargetException {
    if (collection != UNINITIALIZED
        && !cmpIteratorDefn.isDependentOnAnyIteratorOfScopeLessThanItsOwn(context)
        && scopeID != IndexCreationHelper.INDEX_QUERY_SCOPE_ID) {
      return collection;
    }
    // limit the scope for evaluation to this RuntimeIterator:
    // we don't want to use this iterator or subsequent ones in the from clause
    // to evaluate this collection.
    collection = cmpIteratorDefn.evaluateCollection(context, this);
    if (collection == null) {
      return null;
    }
    // if we already have a more specific elementType, set it in the collection
    if (!elementType.equals(TypeUtils.OBJECT_TYPE)) {
      collection.setElementType(elementType);
    } else {
      // The elementType in the Collection obtained is more specific . So use that type.
      elementType = collection.getCollectionType().getElementType();
    }
    return collection;
  }

  @Override
  public Set computeDependencies(ExecutionContext context) {
    // called as the receiver of Path or Operation
    return Collections.singleton(this);
  }

  @Override
  public boolean isDependentOnIterator(RuntimeIterator itr, ExecutionContext context) {
    if (itr == this)
      return true; // never true(?)
    return cmpIteratorDefn.isDependentOnIterator(itr, context);
  }

  @Override
  public boolean isDependentOnCurrentScope(ExecutionContext context) {
    return cmpIteratorDefn.isDependentOnCurrentScope(context);
  }

  public void setCurrent(Object current) {
    this.current = current;
  }

  @Override
  public Object evaluate(ExecutionContext context) {
    Support.Assert(current != UNINITIALIZED,
        "error to evaluate RuntimeIterator without setting current first");
    return current;
  }

  boolean containsProperty(ExecutionContext context, String name, int numArgs,
      boolean mustBeMethod) {
    // first handle structs
    if ((elementType instanceof StructType) && !mustBeMethod) {
      // check field names
      String[] fieldName = ((StructType) elementType).getFieldNames();
      for (String s : fieldName) {
        if (name.equals(s)) {
          return true;
        }
      }
    }
    Class<?> clazz = elementType.resolveClass();
    if (numArgs > 0 || mustBeMethod) {
      // if numArgs==0, then just look up method directly
      // instead of sifting through all methods
      if (numArgs == 0) {
        try {
          clazz.getMethod(name, (Class[]) null);
          return true;
        } catch (NoSuchMethodException e) {
          return false;
        }
      }
      // enumerate methods and match with name
      // here, only check for a method with the same number of arguments.
      // we'll check for ambiguous method invocation when the method is
      // actually fully resolved and invoked
      Method[] methods = clazz.getMethods();
      for (Method m : methods) {
        if (m.getName().equals(name) && m.getParameterTypes().length == numArgs) {
          return true;
        }
      }
      return false;
    }
    // if there are zero arguments and it's an attribute, then defer to
    // AttributeDescriptor
    // to see if there's a match
    return new AttributeDescriptor(context.getCache().getPdxRegistry(),
        context.getCache().getQueryService().getMethodInvocationAuthorizer(), name)
            .validateReadType(clazz);
  }

  @Override
  public String toString() {
    return getClass().getName() + " (name=" + name + " collection expr=" + cmpIteratorDefn + ")";
  }

  // Canonicalization
  void setInternalId(String id) {
    // it's okay for this to be set more than once; a RuntimeIterator
    // can be bound to a scope to compute dependencies, then
    // re-bound to a different scope later at eval time.
    // Support.Assert((internalId == null), "Internal ID is already set");
    Support.Assert((id != null), "Internal ID can not be null");
    internalId = id;
  }

  public String getInternalId() {
    // Support.Assert((internalId != null), "Internal ID is not yet set");
    return internalId;
  }

  public void setDefinition(String def) {
    Support.Assert((definition == null), "Definition is already set");
    Support.Assert((def != null), "Definition can not be null");
    definition = def;
  }

  public void setIndexInternalID(String index_id) {
    this.index_internal_id = index_id;
  }

  public String getIndexInternalID() {
    return index_internal_id;
  }

  public String getDefinition() {
    Support.Assert((definition != null), "Definition is not yet set");
    return definition;
  }

  @Override
  public void generateCanonicalizedExpression(StringBuilder clauseBuffer,
      ExecutionContext context) {
    // prepend the internal iterator variable name for this RunTimeIterator
    int currScopeID = context.currentScope().getScopeID();
    if (currScopeID == scopeID) {
      // should have been set at this point
      clauseBuffer.insert(0, index_internal_id == null ? internalId : index_internal_id);
    } else {
      clauseBuffer.insert(0, internalId).insert(0, '_').insert(0, scopeID).insert(0, "scope");
    }
  }

  void setScopeID(int scopeID) {
    this.scopeID = scopeID;
  }

  int getScopeID() {
    return scopeID;
  }
}
