/*
 * 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.dev.jjs.impl;

import com.google.gwt.dev.jjs.InternalCompilerException;
import com.google.gwt.dev.jjs.SourceInfo;
import com.google.gwt.dev.jjs.SourceOrigin;
import com.google.gwt.dev.jjs.ast.JArrayType;
import com.google.gwt.dev.jjs.ast.JClassType;
import com.google.gwt.dev.jjs.ast.JConstructor;
import com.google.gwt.dev.jjs.ast.JDeclaredType;
import com.google.gwt.dev.jjs.ast.JEnumType;
import com.google.gwt.dev.jjs.ast.JField;
import com.google.gwt.dev.jjs.ast.JInterfaceType;
import com.google.gwt.dev.jjs.ast.JMethod;
import com.google.gwt.dev.jjs.ast.JNullType;
import com.google.gwt.dev.jjs.ast.JParameter;
import com.google.gwt.dev.jjs.ast.JPrimitiveType;
import com.google.gwt.dev.jjs.ast.JReferenceType;
import com.google.gwt.dev.jjs.ast.JType;
import com.google.gwt.dev.util.StringInterner;

import org.eclipse.jdt.internal.compiler.lookup.ArrayBinding;
import org.eclipse.jdt.internal.compiler.lookup.BaseTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Creates unresolved references to types, fields, and methods.
 */
public class ReferenceMapper {

  private final List<String> argNames = new ArrayList<String>();
  private final Map<String, JField> fields = new HashMap<String, JField>();
  private final Map<String, JMethod> methods = new HashMap<String, JMethod>();
  private final Map<String, JField> sourceFields = new HashMap<String, JField>();
  private final Map<String, JMethod> sourceMethods = new HashMap<String, JMethod>();
  private final Map<String, JReferenceType> sourceTypes = new HashMap<String, JReferenceType>();
  private final StringInterner stringInterner = StringInterner.get();
  private final Map<String, JType> types = new HashMap<String, JType>();

  {
    put(JPrimitiveType.BOOLEAN, JPrimitiveType.BYTE, JPrimitiveType.CHAR, JPrimitiveType.DOUBLE,
        JPrimitiveType.FLOAT, JPrimitiveType.INT, JPrimitiveType.LONG, JPrimitiveType.SHORT,
        JPrimitiveType.VOID, JNullType.INSTANCE);
  }

  public void clearSource() {
    sourceFields.clear();
    sourceMethods.clear();
    sourceTypes.clear();
  }

  public JField get(FieldBinding binding) {
    binding = binding.original();
    String key = signature(binding);
    JField sourceField = sourceFields.get(key);
    if (sourceField != null) {
      assert !sourceField.isExternal();
      return sourceField;
    }
    JField field = fields.get(key);
    if (field == null) {
      field = createField(binding);
      assert field.isExternal();
      fields.put(key, field);
    }
    return field;
  }

  public JMethod get(MethodBinding binding) {
    binding = binding.original();
    String key = signature(binding);
    JMethod sourceMethod = sourceMethods.get(key);
    if (sourceMethod != null) {
      assert !sourceMethod.isExternal();
      return sourceMethod;
    }
    JMethod method = methods.get(key);
    if (method == null) {
      if (binding.isConstructor()) {
        method = createConstructor(SourceOrigin.UNKNOWN, binding);
      } else {
        method = createMethod(SourceOrigin.UNKNOWN, binding, null);
      }
      assert method.isExternal();
      methods.put(key, method);
    }
    return method;
  }

  public JType get(TypeBinding binding) {
    binding = binding.erasure();
    String key = signature(binding);
    JReferenceType sourceType = sourceTypes.get(key);
    if (sourceType != null) {
      assert !sourceType.isExternal();
      return sourceType;
    }

    JType type = types.get(key);
    if (type != null) {
      assert type instanceof JPrimitiveType || type == JNullType.INSTANCE || type.isExternal();
      return type;
    }
    assert !(binding instanceof BaseTypeBinding);

    if (binding instanceof ArrayBinding) {
      ArrayBinding arrayBinding = (ArrayBinding) binding;
      JArrayType arrayType = new JArrayType(get(arrayBinding.elementsType()));
      if (arrayType.isExternal()) {
        types.put(key, arrayType);
      } else {
        sourceTypes.put(key, arrayType);
      }
      return arrayType;
    } else {
      ReferenceBinding refBinding = (ReferenceBinding) binding;
      JDeclaredType declType = createType(refBinding);
      if (declType instanceof JClassType) {
        ReferenceBinding superclass = refBinding.superclass();
        if (superclass != null) {
          ((JClassType) declType).setSuperClass((JClassType) get(superclass));
        }
      }
      ReferenceBinding[] superInterfaces = refBinding.superInterfaces();
      if (superInterfaces != null) {
        for (ReferenceBinding intf : superInterfaces) {
          declType.addImplements((JInterfaceType) get(intf));
        }
      }
      // Emulate clinit method for super clinit calls.
      JMethod clinit =
          new JMethod(SourceOrigin.UNKNOWN, "$clinit", declType, JPrimitiveType.VOID, false, true,
              true, true);
      clinit.freezeParamTypes();
      clinit.setSynthetic();
      declType.addMethod(clinit);
      declType.setExternal(true);
      types.put(key, declType);
      return declType;
    }
  }

  public void setField(FieldBinding binding, JField field) {
    String key = signature(binding);
    sourceFields.put(key, field);
  }

  public void setMethod(MethodBinding binding, JMethod method) {
    String key = signature(binding);
    sourceMethods.put(key, method);
  }

  public void setSourceType(SourceTypeBinding binding, JDeclaredType type) {
    String key = signature(binding);
    sourceTypes.put(key, type);
  }

  JMethod createConstructor(SourceInfo info, MethodBinding b) {
    JDeclaredType enclosingType = (JDeclaredType) get(b.declaringClass);
    JMethod method = new JConstructor(info, (JClassType) enclosingType);
    enclosingType.addMethod(method);

    /*
     * Don't need to synthesize enum intrinsic args because enum ctors can only
     * be called locally.
     */

    int argPosition = 0;

    ReferenceBinding declaringClass = b.declaringClass;
    if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
      // add synthetic args for outer this
      if (declaringClass.syntheticEnclosingInstanceTypes() != null) {
        for (ReferenceBinding argType : declaringClass.syntheticEnclosingInstanceTypes()) {
          createParameter(info, argType, method, argPosition++);
        }
      }
    }

    // User args.
    argPosition = mapParameters(info, method, b, argPosition);

    if (declaringClass.isNestedType() && !declaringClass.isStatic()) {
      // add synthetic args for locals
      if (declaringClass.syntheticOuterLocalVariables() != null) {
        for (SyntheticArgumentBinding arg : declaringClass.syntheticOuterLocalVariables()) {
          createParameter(info, arg.type, method, argPosition++);
        }
      }
    }

    mapExceptions(method, b);
    if (b.isSynthetic()) {
      method.setSynthetic();
    }
    return method;
  }

  JMethod createMethod(SourceInfo info, MethodBinding b, String[] paramNames) {
    JDeclaredType enclosingType = (JDeclaredType) get(b.declaringClass);
    JMethod method =
        new JMethod(info, intern(b.selector), enclosingType, get(b.returnType), b.isAbstract(), b
            .isStatic(), b.isFinal(), b.isPrivate());
    enclosingType.addMethod(method);
    if (paramNames == null) {
      mapParameters(info, method, b, 0);
    } else {
      mapParameters(info, method, b, paramNames);
    }
    mapExceptions(method, b);
    if (b.isSynthetic()) {
      method.setSynthetic();
    }
    return method;
  }

  private JField createField(FieldBinding binding) {
    JDeclaredType enclosingType = (JDeclaredType) get(binding.declaringClass);
    JField field =
        new JField(SourceOrigin.UNKNOWN, intern(binding.name), enclosingType, get(binding.type),
            binding.isStatic(), GwtAstBuilder.getFieldDisposition(binding));
    enclosingType.addField(field);
    return field;
  }

  private JParameter createParameter(SourceInfo info, TypeBinding paramType,
      JMethod enclosingMethod, int argPosition) {
    JType type = get(paramType);
    ensureArgNames(argPosition);
    JParameter param =
        new JParameter(info, argNames.get(argPosition), type, true, false, enclosingMethod);
    enclosingMethod.addParam(param);
    return param;
  }

  private JParameter createParameter(SourceInfo info, TypeBinding paramType,
      JMethod enclosingMethod, String name) {
    JParameter param = new JParameter(info, name, get(paramType), true, false, enclosingMethod);
    enclosingMethod.addParam(param);
    return param;
  }

  private JDeclaredType createType(ReferenceBinding binding) {
    String name = GwtAstBuilder.dotify(binding.compoundName);
    SourceInfo info = SourceOrigin.UNKNOWN;
    if (binding.isClass()) {
      return new JClassType(info, name, binding.isAbstract(), binding.isFinal());
    } else if (binding.isInterface() || binding.isAnnotationType()) {
      return new JInterfaceType(info, name);
    } else if (binding.isEnum()) {
      if (binding.isAnonymousType()) {
        // Don't model an enum subclass as a JEnumType.
        return new JClassType(info, name, false, true);
      } else {
        return new JEnumType(info, name, binding.isAbstract());
      }
    } else {
      throw new InternalCompilerException("ReferenceBinding is not a class, interface, or enum.");
    }
  }

  private void ensureArgNames(int required) {
    for (int i = argNames.size(); i <= required; ++i) {
      argNames.add(intern("arg" + i));
    }
  }

  private String intern(char[] cs) {
    return intern(String.valueOf(cs));
  }

  private String intern(String s) {
    return stringInterner.intern(s);
  }

  private void mapExceptions(JMethod method, MethodBinding binding) {
    for (ReferenceBinding thrownBinding : binding.thrownExceptions) {
      JClassType type = (JClassType) get(thrownBinding);
      method.addThrownException(type);
    }
  }

  private int mapParameters(SourceInfo info, JMethod method, MethodBinding binding, int argPosition) {
    if (binding.parameters != null) {
      ensureArgNames(argPosition + binding.parameters.length);
      for (TypeBinding argType : binding.parameters) {
        createParameter(info, argType, method, argNames.get(argPosition++));
      }
    }
    method.freezeParamTypes();
    return argPosition;
  }

  private void mapParameters(SourceInfo info, JMethod method, MethodBinding binding,
      String[] paramNames) {
    if (binding.parameters != null) {
      int i = 0;
      for (TypeBinding argType : binding.parameters) {
        createParameter(info, argType, method, paramNames[i++]);
      }
    }
    method.freezeParamTypes();
  }

  private void put(JType... baseTypes) {
    for (JType type : baseTypes) {
      types.put(type.getName(), type);
    }
  }

  private String signature(FieldBinding binding) {
    StringBuilder sb = new StringBuilder();
    sb.append(binding.declaringClass.constantPoolName());
    sb.append('.');
    sb.append(binding.name);
    sb.append(':');
    sb.append(binding.type.signature());
    return sb.toString();
  }

  private String signature(MethodBinding binding) {
    StringBuilder sb = new StringBuilder();
    sb.append(binding.declaringClass.constantPoolName());
    sb.append('.');
    sb.append(binding.selector);
    sb.append('(');
    for (TypeBinding paramType : binding.parameters) {
      sb.append(paramType.signature());
    }
    sb.append(')');
    sb.append(binding.returnType.signature());
    return sb.toString();
  }

  private String signature(TypeBinding binding) {
    if (binding.isBaseType()) {
      return String.valueOf(binding.sourceName());
    } else {
      return String.valueOf(binding.constantPoolName());
    }
  }
}
