/*
 * 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.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import org.apache.geode.cache.query.AmbiguousNameException;
import org.apache.geode.cache.query.NameNotFoundException;
import org.apache.geode.cache.query.NameResolutionException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.cache.query.Struct;
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.ObjectType;


/**
 * Class Description
 *
 * @version $Revision: 1.1 $
 */

public class PathUtils {

  public static String[] tokenizePath(String path) {
    ArrayList alist = new ArrayList();
    StringTokenizer tokenizer = new StringTokenizer(path, ".");
    while (tokenizer.hasMoreTokens()) {
      alist.add(tokenizer.nextToken());
    }
    return (String[]) alist.toArray(new String[0]);
  }

  public static String buildPathString(String[] path) {
    Support.assertArg(path != null && path.length > 0, "path should not be null or empty");
    StringBuffer buf = new StringBuffer();
    buf.append(path[0]);
    for (int i = 1; i < path.length; i++) {
      buf.append('.');
      buf.append(path[i]);
    }
    return buf.toString();
  }

  public static Object evaluateAttribute(ExecutionContext context, Object target, String attribute)
      throws NameNotFoundException, QueryInvocationTargetException {
    if (target instanceof Struct) {
      Struct struct = (Struct) target;
      try {
        return struct.get(attribute);
      } catch (Exception e) {
        throw new NameNotFoundException(attribute);
      }
    }

    try {
      return new AttributeDescriptor(context.getCache().getPdxRegistry(), attribute)
          .read(target, context);
    } catch (NameNotFoundException nfe) {
      if (DefaultQueryService.QUERY_HETEROGENEOUS_OBJECTS
          || DefaultQueryService.TEST_QUERY_HETEROGENEOUS_OBJECTS) {
        return QueryService.UNDEFINED;
      } else {
        throw nfe;
      }
    }
  }

  /*
   * This was added as part of CQ performance changes. The change is done to re-use the
   * AttributeDescriptor object instead of creating it each time.
   */
  /*
   * public static Object evaluateAttribute(Object target, String attribute, AttributeDescriptor
   * attributeDescriptor) throws NameNotFoundException, QueryInvocationTargetException { if(target
   * instanceof Struct){ Struct struct = (Struct)target; try{ return struct.get(attribute);
   * }catch(Exception e){ throw new NameNotFoundException(attribute); } } return
   * attributeDescriptor.read(target); }
   */

  /**
   * @param pathArray the path starting with an attribute on the initial type.
   * @return array of types starting with the initialType and ending with the type of the last
   *         attribute in the path.
   * @throws NameNotFoundException if could not find an attribute along path
   *
   */
  public static ObjectType[] calculateTypesAlongPath(ExecutionContext context,
      ObjectType initialType, String[] pathArray) throws NameNotFoundException {
    ObjectType[] types = new ObjectType[pathArray.length + 1];
    // initialClass goes in front
    types[0] = initialType;

    for (int i = 1; i < types.length; i++) {
      ObjectType currentType = types[i - 1];
      Member member = new AttributeDescriptor(context.getCache().getPdxRegistry(), pathArray[i - 1])
          .getReadMember(currentType.resolveClass());

      if (member instanceof Field)
        types[i] = TypeUtils.getObjectType(((Field) member).getType());
      else if (member instanceof Method)
        types[i] = TypeUtils.getObjectType(((Method) member).getReturnType());
    }
    return types;
  }


  public static ObjectType computeElementTypeOfExpression(ExecutionContext context,
      CompiledValue expr) throws AmbiguousNameException {
    try {

      ObjectType type = TypeUtils.OBJECT_TYPE;
      List exprSteps = new ArrayList();
      while (true) {
        if (expr instanceof CompiledPath) {
          CompiledPath path = (CompiledPath) expr;
          exprSteps.add(0, path.getTailID());
          expr = path.getReceiver();
        } else if (expr instanceof CompiledOperation) {
          CompiledOperation operation = (CompiledOperation) expr;
          if (operation.getArguments().size() > 0) {
            return TypeUtils.OBJECT_TYPE;
          }
          exprSteps.add(0, operation.getMethodName() + "()");
          expr = operation.getReceiver(context);
          if (expr == null) {
            expr = context.resolveImplicitOperationName(operation.getMethodName(),
                operation.getArguments().size(), true);
          }
        } else if (expr instanceof CompiledID) {
          expr = context.resolve(((CompiledID) expr).getId());
        } else if (expr instanceof CompiledRegion) {
          QRegion qrgn = (QRegion) ((CompiledRegion) expr).evaluate(context);
          type = qrgn.getCollectionType();
          break;
        } else if (expr instanceof RuntimeIterator) {
          type = ((RuntimeIterator) expr).getElementType();
          break;
        } else {
          return TypeUtils.OBJECT_TYPE;
        }
      }
      if (!TypeUtils.OBJECT_TYPE.equals(type)) {
        Class clazz = type.resolveClass();
        for (int i = 0; i < exprSteps.size(); i++) {
          Member member;
          String stepStr = (String) exprSteps.get(i);
          // System.out.println("step = "+step);
          if (stepStr.endsWith("()")) {
            stepStr = stepStr.substring(0, stepStr.length() - 2);
            member = clazz.getMethod(stepStr, (Class[]) null);
          } else {
            member = new AttributeDescriptor(context.getCache().getPdxRegistry(), stepStr)
                .getReadMember(clazz);
          }

          if (member instanceof Field) {
            clazz = ((Field) member).getType();
          } else if (member instanceof Method) {
            clazz = ((Method) member).getReturnType();
          }
          type = TypeUtils.getObjectType(clazz);
        }
        return type;
      }
    } catch (NoSuchMethodException e) {
    } catch (NameResolutionException e) {
    } catch (TypeMismatchException e) {
    }
    return TypeUtils.OBJECT_TYPE;
  }

  /**
   * Collects all the compiled values in the path , starting from the self at position 0 in the
   * returned List
   *
   * @return List of CompiledValues ( includes the RuntimeIterator)
   */
  public static List<CompiledValue> collectCompiledValuesInThePath(CompiledValue expr,
      ExecutionContext context) throws AmbiguousNameException, TypeMismatchException {
    boolean toContinue = true;
    List<CompiledValue> retList = new ArrayList<CompiledValue>();

    int exprType = expr.getType();
    while (toContinue) {
      switch (exprType) {
        case OQLLexerTokenTypes.RegionPath:
          retList.add(expr);
          toContinue = false;
          break;
        case OQLLexerTokenTypes.METHOD_INV:
          retList.add(expr);
          CompiledOperation operation = (CompiledOperation) expr;
          expr = operation.getReceiver(null/*
                                            * pass the ExecutionContext as null, thus never
                                            * implicitly resolving to RuntimeIterator
                                            */);
          if (expr == null) {
            expr = operation;
            toContinue = false;
          }
          break;
        case CompiledValue.PATH:
          retList.add(expr);
          expr = ((CompiledPath) expr).getReceiver();
          break;
        case OQLLexerTokenTypes.ITERATOR_DEF:
          retList.add(expr);
          toContinue = false;
          break;
        case OQLLexerTokenTypes.TOK_LBRACK:
          retList.add(expr);
          expr = ((CompiledIndexOperation) expr).getReceiver();
          break;
        case OQLLexerTokenTypes.Identifier:
          CompiledID cid = (CompiledID) expr;
          expr = context.resolve(cid.getId());
          break;
        default:
          toContinue = false;
          break;
      }

      if (toContinue)
        exprType = expr.getType();
    }
    return retList;
  }

}
