/*
 * Copyright 2010 Google Inc.
 * 
 * Licensed 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 com.google.gwt.autobean.server;

import com.google.gwt.autobean.server.impl.TypeUtils;
import com.google.gwt.autobean.shared.AutoBean;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * Breakout of method types that an AutoBean shim interface can implement. The
 * order of the values of the enum is important.
 */
enum BeanMethod {
  /**
   * Methods defined in Object.
   */
  OBJECT {
    @Override
    Object invoke(SimpleBeanHandler<?> handler, Method method, Object[] args)
        throws Throwable {
      if (CALL.matches(handler, method)) {
        return CALL.invoke(handler, method, args);
      }
      return method.invoke(handler, args);
    }

    @Override
    boolean matches(SimpleBeanHandler<?> handler, Method method) {
      return method.getDeclaringClass().equals(Object.class);
    }
  },
  /**
   * Getters.
   */
  GET {
    @Override
    Object invoke(SimpleBeanHandler<?> handler, Method method, Object[] args) {
      String propertyName;
      String name = method.getName();
      if (Boolean.TYPE.equals(method.getReturnType()) && name.startsWith("is")) {
        propertyName = name.substring(2);
      } else {
        // A regular getter or a boolean hasFoo()
        propertyName = name.substring(3);
      }
      Object toReturn = handler.getBean().getValues().get(propertyName);
      if (toReturn == null && method.getReturnType().isPrimitive()) {
        toReturn = TypeUtils.getDefaultPrimitiveValue(method.getReturnType());
      }
      return toReturn;
    }

    @Override
    boolean matches(SimpleBeanHandler<?> handler, Method method) {
      Class<?> returnType = method.getReturnType();
      if (method.getParameterTypes().length != 0
          || Void.TYPE.equals(returnType)) {
        return false;
      }

      String name = method.getName();
      if (Boolean.TYPE.equals(returnType)) {
        if (name.startsWith("is") && name.length() > 2
            || name.startsWith("has") && name.length() > 3) {
          return true;
        }
      }
      return name.startsWith("get") && name.length() > 3;
    }
  },
  /**
   * Setters.
   */
  SET {
    @Override
    Object invoke(SimpleBeanHandler<?> handler, Method method, Object[] args) {
      handler.getBean().getValues().put(method.getName().substring(3), args[0]);
      return null;
    }

    @Override
    boolean matches(SimpleBeanHandler<?> handler, Method method) {
      String name = method.getName();
      return name.startsWith("set") && name.length() > 3
          && method.getParameterTypes().length == 1
          && method.getReturnType().equals(Void.TYPE);
    }
  },
  /**
   * Domain methods.
   */
  CALL {
    @Override
    Object invoke(SimpleBeanHandler<?> handler, Method method, Object[] args)
        throws Throwable {
      if (args == null) {
        args = EMPTY_OBJECT;
      }

      Method found = findMethod(handler, method);
      if (found != null) {
        Object[] realArgs = new Object[args.length + 1];
        realArgs[0] = handler.getBean();
        System.arraycopy(args, 0, realArgs, 1, args.length);
        return found.invoke(null, realArgs);
      }
      throw new RuntimeException("Could not find category implementation of "
          + method.toGenericString());
    }

    @Override
    boolean matches(SimpleBeanHandler<?> handler, Method method) {
      return handler.getBean().isWrapper()
          || !handler.getBean().getConfiguration().getCategories().isEmpty()
          && findMethod(handler, method) != null;
    }
  };

  private static final Object[] EMPTY_OBJECT = new Object[0];

  static Method findMethod(SimpleBeanHandler<?> handler, Method method) {
    Class<?>[] declaredParams = method.getParameterTypes();
    Class<?>[] searchParams = new Class<?>[declaredParams.length + 1];
    searchParams[0] = AutoBean.class;
    System.arraycopy(declaredParams, 0, searchParams, 1, declaredParams.length);
    Class<?> autoBeanType = handler.getBean().getType();

    for (Class<?> clazz : handler.getBean().getConfiguration().getCategories()) {
      try {
        Method found = clazz.getMethod(method.getName(), searchParams);
        if (!Modifier.isStatic(found.getModifiers())) {
          continue;
        }
        // Check the AutoBean parameterization of the 0th argument
        Class<?> foundAutoBean = TypeUtils.ensureBaseType(TypeUtils.getSingleParameterization(
            AutoBean.class, found.getGenericParameterTypes()[0]));
        if (!foundAutoBean.isAssignableFrom(autoBeanType)) {
          continue;
        }
        return found;
      } catch (NoSuchMethodException expected) {
      } catch (IllegalArgumentException e) {
        throw new RuntimeException(e);
      }
    }
    return null;
  }

  /**
   * Invoke the method.
   */
  abstract Object invoke(SimpleBeanHandler<?> handler, Method method,
      Object[] args) throws Throwable;

  /**
   * Convenience method, not valid for {@link BeanMethod#CALL}.
   */
  boolean matches(Method method) {
    return matches(null, method);
  }

  /**
   * Determine if the method maches the given type.
   */
  abstract boolean matches(SimpleBeanHandler<?> handler, Method method);
}