/*
 * 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 static org.apache.geode.cache.query.security.RestrictedMethodAuthorizer.UNAUTHORIZED_STRING;

import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.cache.EntryDestroyedException;
import org.apache.geode.cache.query.NameNotFoundException;
import org.apache.geode.cache.query.QueryInvocationTargetException;
import org.apache.geode.cache.query.QueryService;
import org.apache.geode.internal.cache.Token;
import org.apache.geode.internal.util.JavaWorkarounds;
import org.apache.geode.pdx.JSONFormatter;
import org.apache.geode.pdx.PdxSerializationException;
import org.apache.geode.pdx.internal.InternalPdxInstance;
import org.apache.geode.pdx.internal.PdxType;
import org.apache.geode.pdx.internal.TypeRegistry;
import org.apache.geode.security.NotAuthorizedException;

/**
 * Utility for managing an attribute
 */
public class AttributeDescriptor {
  private final String _name;
  private final TypeRegistry _pdxRegistry;
  /** cache for remembering the correct Member for a class and attribute */
  @MakeNotStatic
  static final ConcurrentMap<List, Member> _localCache = new ConcurrentHashMap<>();

  public AttributeDescriptor(TypeRegistry pdxRegistry, String name) {
    _name = name;
    _pdxRegistry = pdxRegistry;
  }

  /** Validate whether this attribute <i>can</i> be evaluated for target type */
  public boolean validateReadType(Class targetType) {
    try {
      getReadMember(targetType);
      return true;
    } catch (NameNotFoundException e) {
      return false;
    }
  }

  public Object read(Object target, ExecutionContext executionContext)
      throws NameNotFoundException, QueryInvocationTargetException {
    if (target == null || target == QueryService.UNDEFINED) {
      return QueryService.UNDEFINED;
    }

    if (target instanceof InternalPdxInstance) {
      return readPdx((InternalPdxInstance) target, executionContext);
    }

    // for non pdx objects
    return readReflection(target, executionContext);
  }

  // used when the resolution of an attribute must be on a superclass
  // instead of the runtime class
  Object readReflection(Object target, ExecutionContext executionContext)
      throws NameNotFoundException, QueryInvocationTargetException {
    Support.Assert(target != null);
    Support.Assert(target != QueryService.UNDEFINED);
    if (target instanceof Token) {
      return QueryService.UNDEFINED;
    }

    Class resolutionClass = target.getClass();
    Member m = getReadMember(resolutionClass);
    try {
      if (m instanceof Method) {
        try {
          Method method = (Method) m;
          // Try to use previous result so authorizer gets invoked only once per query.
          boolean authorizationResult;
          String cacheKey = target.getClass().getCanonicalName() + "." + method.getName();
          Boolean cachedResult = (Boolean) executionContext.cacheGet(cacheKey);

          if (cachedResult == null) {
            // First time, evaluate and cache result.
            authorizationResult =
                executionContext.getMethodInvocationAuthorizer().authorize(method, target);
            executionContext.cachePut(cacheKey, authorizationResult);
          } else {
            // Use cached result.
            authorizationResult = cachedResult;
          }

          if (!authorizationResult) {
            throw new NotAuthorizedException(UNAUTHORIZED_STRING + method.getName());
          }

          return method.invoke(target, (Object[]) null);
        } catch (EntryDestroyedException e) {
          // eat the Exception
          return QueryService.UNDEFINED;
        } catch (IllegalAccessException e) {
          throw new NameNotFoundException(
              String.format(
                  "Method ' %s ' in class ' %s ' is not accessible to the query processor",
                  m.getName(), target.getClass().getName()),
              e);
        } catch (InvocationTargetException e) {
          // if the target exception is Exception, wrap that,
          // otherwise wrap the InvocationTargetException itself
          Throwable t = e.getTargetException();
          if ((t instanceof EntryDestroyedException)) {
            // eat the exception
            return QueryService.UNDEFINED;
          }
          if (t instanceof Exception)
            throw new QueryInvocationTargetException(t);
          throw new QueryInvocationTargetException(e);
        }
      } else {
        try {
          return ((Field) m).get(target);
        } catch (IllegalAccessException e) {
          throw new NameNotFoundException(
              String.format(
                  "Field ' %s ' in class ' %s ' is not accessible to the query processor",
                  m.getName(), target.getClass().getName()),
              e);
        } catch (EntryDestroyedException e) {
          return QueryService.UNDEFINED;
        }
      }
    } catch (EntryDestroyedException e) {
      // eat the exception
      return QueryService.UNDEFINED;
    }
  }

  @SuppressWarnings("unchecked")
  Member getReadMember(Class targetClass) throws NameNotFoundException {
    // mapping: public field (same name), method (getAttribute()), method (attribute())
    List key = new ArrayList();
    key.add(targetClass);
    key.add(_name);

    Member m = JavaWorkarounds.computeIfAbsent(_localCache, key, k -> {
      Member member = getReadField(targetClass);
      return member == null ? getReadMethod(targetClass) : member;
    });

    if (m == null) {
      throw new NameNotFoundException(String.format(
          "No public attribute named ' %s ' was found in class %s", _name, targetClass.getName()));
    }

    // override security for nonpublic derived classes with public members
    ((AccessibleObject) m).setAccessible(true);
    return m;
  }

  Field getReadField(Class targetType) {
    try {
      return targetType.getField(_name);
    } catch (NoSuchFieldException e) {
      return null;
    }
  }

  Method getReadMethod(Class targetType) {
    Method m;
    // Check for a getter method for this _name
    String beanMethod = "get" + _name.substring(0, 1).toUpperCase() + _name.substring(1);
    m = getReadMethod(targetType, beanMethod);

    if (m != null)
      return m;

    return getReadMethod(targetType, _name);
  }

  @SuppressWarnings("unchecked")
  Method getReadMethod(Class targetType, String methodName) {
    try {
      return targetType.getMethod(methodName, (Class[]) null);
    } catch (NoSuchMethodException e) {
      updateClassToMethodsMap(targetType.getCanonicalName(), _name);
      return null;
    }
  }

  /**
   * reads field value from a PdxInstance
   *
   * @return the value of the field from PdxInstance
   */
  private Object readPdx(InternalPdxInstance pdxInstance, ExecutionContext executionContext)
      throws NameNotFoundException, QueryInvocationTargetException {
    // if the field is present in the pdxinstance
    if (pdxInstance.hasField(_name)) {
      // return PdxString if field is a String otherwise invoke readField
      return pdxInstance.getRawField(_name);
    } else {
      // field not found in the pdx instance, look for the field in any of the
      // PdxTypes (versions of the pdxinstance) in the type registry
      String className = pdxInstance.getClassName();

      // don't look further for field or method or reflect on GemFire JSON data
      if (className.equals(JSONFormatter.JSON_CLASSNAME)) {
        return QueryService.UNDEFINED;
      }

      // check if the field was not found previously
      if (!isFieldAlreadySearchedAndNotFound(className, _name)) {
        PdxType pdxType = _pdxRegistry.getPdxTypeForField(_name, className);
        if (pdxType == null) {
          // remember the field that is not present in any version to avoid
          // trips to the registry next time
          updateClassToFieldsMap(className, _name);
        } else {
          return pdxType.getPdxField(_name).getFieldType().getDefaultValue();
        }
      }
      // if the field is not present in any of the versions try to
      // invoke implicit method call
      if (!this.isMethodAlreadySearchedAndNotFound(className, _name)) {
        try {
          return readFieldFromDeserializedObject(pdxInstance, executionContext);
        } catch (NameNotFoundException ex) {
          updateClassToMethodsMap(pdxInstance.getClassName(), _name);
          throw ex;
        }
      } else
        return QueryService.UNDEFINED;
    }
  }

  private Object readFieldFromDeserializedObject(InternalPdxInstance pdxInstance,
      ExecutionContext executionContext)
      throws NameNotFoundException, QueryInvocationTargetException {
    Object obj;

    try {
      obj = pdxInstance.getCachedObject();
    } catch (PdxSerializationException e) {
      throw new NameNotFoundException( // the domain object is not available
          String.format("Field '%s' is not accessible to the query processor because: %s",
              _name, e.getMessage()));
    }

    return readReflection(obj, executionContext);
  }

  private void updateClassToFieldsMap(String className, String field) {
    Map<String, Set<String>> map = DefaultQuery.getPdxClasstofieldsmap();
    Set<String> fields = map.get(className);
    if (fields == null) {
      fields = new HashSet<>();
      map.put(className, fields);
    }

    fields.add(field);
  }

  private boolean isFieldAlreadySearchedAndNotFound(String className, String field) {
    Set<String> fields = DefaultQuery.getPdxClasstofieldsmap().get(className);
    if (fields != null) {
      return fields.contains(field);
    }

    return false;
  }

  private void updateClassToMethodsMap(String className, String field) {
    Map<String, Set<String>> map = DefaultQuery.getPdxClasstoMethodsmap();
    Set<String> fields = map.get(className);
    if (fields == null) {
      fields = new HashSet<>();
      map.put(className, fields);
    }

    fields.add(field);
  }

  private boolean isMethodAlreadySearchedAndNotFound(String className, String field) {
    Set<String> fields = DefaultQuery.getPdxClasstoMethodsmap().get(className);
    if (fields != null) {
      return fields.contains(field);
    }

    return false;
  }
}
