/*
 * 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.rebind.model;

import com.google.gwt.autobean.shared.AutoBean.PropertyName;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JEnumConstant;
import com.google.gwt.core.ext.typeinfo.JEnumType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.editor.rebind.model.ModelUtils;

import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * Describes a method implemented by an AutoBean.
 */
public class AutoBeanMethod {
  /**
   * Creates AutoBeanMethods.
   */
  public static class Builder {
    private AutoBeanMethod toReturn = new AutoBeanMethod();

    public AutoBeanMethod build() {
      if (toReturn.action.equals(JBeanMethod.GET)
          || toReturn.action.equals(JBeanMethod.SET)
          || toReturn.action.equals(JBeanMethod.SET_BUILDER)) {
        PropertyName annotation = toReturn.method.getAnnotation(PropertyName.class);
        if (annotation != null) {
          toReturn.propertyName = annotation.value();
        } else {
          toReturn.propertyName = toReturn.action.inferName(toReturn.method);
        }
      }

      try {
        return toReturn;
      } finally {
        toReturn = null;
      }
    }

    public void setAction(JBeanMethod action) {
      toReturn.action = action;
    }

    public void setMethod(JMethod method) {
      toReturn.method = method;
      TypeOracle oracle = method.getEnclosingType().getOracle();

      JType returnType = method.getReturnType();
      toReturn.isValueType = ModelUtils.isValueType(oracle, returnType);

      if (!toReturn.isValueType) {
        // See if it's a collection or a map
        JClassType returnClass = returnType.isClassOrInterface();
        JClassType collectionInterface = oracle.findType(Collection.class.getCanonicalName());
        JClassType mapInterface = oracle.findType(Map.class.getCanonicalName());
        if (collectionInterface.isAssignableFrom(returnClass)) {
          JClassType[] parameterizations = ModelUtils.findParameterizationOf(
              collectionInterface, returnClass);
          toReturn.elementType = parameterizations[0];
          maybeProcessEnumType(toReturn.elementType);
        } else if (mapInterface.isAssignableFrom(returnClass)) {
          JClassType[] parameterizations = ModelUtils.findParameterizationOf(
              mapInterface, returnClass);
          toReturn.keyType = parameterizations[0];
          toReturn.valueType = parameterizations[1];
          maybeProcessEnumType(toReturn.keyType);
          maybeProcessEnumType(toReturn.valueType);
        }
      } else {
        maybeProcessEnumType(returnType);
      }
    }

    public void setNoWrap(boolean noWrap) {
      toReturn.isNoWrap = noWrap;
    }

    public void setStaticImp(JMethod staticImpl) {
      toReturn.staticImpl = staticImpl;
    }

    /**
     * Call {@link #processEnumType(JEnumType)} if {@code type} is a
     * {@link JEnumType}.
     */
    private void maybeProcessEnumType(JType type) {
      assert type != null : "type == null";
      JEnumType enumType = type.isEnum();
      if (enumType != null) {
        processEnumType(enumType);
      }
    }

    /**
     * Adds a JEnumType to the AutoBeanMethod's enumMap so that the
     * AutoBeanFactoryGenerator can embed extra metadata about the enum values.
     */
    private void processEnumType(JEnumType enumType) {
      Map<JEnumConstant, String> map = toReturn.enumMap;
      if (map == null) {
        map = toReturn.enumMap = new LinkedHashMap<JEnumConstant, String>();
      }
      for (JEnumConstant e : enumType.getEnumConstants()) {
        String name = getEnumName(e);
        map.put(e, name);
      }
    }
  }

  static String getEnumName(JEnumConstant e) {
    String name;
    PropertyName annotation = e.getAnnotation(PropertyName.class);
    if (annotation == null) {
      name = e.getName();
    } else {
      name = annotation.value();
    }
    return name;
  }

  private JBeanMethod action;
  private JClassType elementType;
  private Map<JEnumConstant, String> enumMap;
  private JClassType keyType;
  private JMethod method;
  private boolean isNoWrap;
  private boolean isValueType;
  private String propertyName;
  private JMethod staticImpl;
  private JClassType valueType;

  private AutoBeanMethod() {
  }

  public JBeanMethod getAction() {
    return action;
  }

  public JClassType getElementType() {
    return elementType;
  }

  public Map<JEnumConstant, String> getEnumMap() {
    return enumMap;
  }

  public JClassType getKeyType() {
    return keyType;
  }

  public JMethod getMethod() {
    return method;
  }

  public String getPropertyName() {
    return propertyName;
  }

  /**
   * If the AutoBean method was declared in a type containing a
   * {@link com.google.gwt.editor.client.AutoBean.Category Category} annotation,
   * this method will return the static implementation.
   */
  public JMethod getStaticImpl() {
    return staticImpl;
  }

  public JClassType getValueType() {
    return valueType;
  }

  public boolean hasEnumMap() {
    return enumMap != null;
  }

  public boolean isCollection() {
    return elementType != null;
  }

  public boolean isMap() {
    return keyType != null;
  }

  public boolean isNoWrap() {
    return isNoWrap;
  }

  public boolean isValueType() {
    return isValueType;
  }

  /**
   * For debugging use only.
   */
  @Override
  public String toString() {
    return method.toString();
  }
}