/*
 * Copyright 2008 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.shell;

import com.google.gwt.dev.util.StringInterner;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;

/**
 * Helper class for dispatching methods to Java objects. It takes methods on
 * various Java classes and assigns DISPID's to them.
 */
public class DispatchClassInfo {
  private Class<?> cls;

  private final int clsId;

  private ArrayList<Member> memberById;

  private HashMap<String, Integer> memberIdByName;

  public DispatchClassInfo(Class<?> cls, int classId) {
    this.cls = cls;
    clsId = classId;
  }

  public int getClassId() {
    return clsId;
  }

  public Member getMember(int id) {
    lazyInitTargetMembers();
    id &= 0xffff;
    return memberById.get(id);
  }

  public int getMemberId(String mangledMemberName) {
    lazyInitTargetMembers();

    Integer id = memberIdByName.get(mangledMemberName);
    if (id == null) {
      return -1;
    }

    return id.intValue();
  }

  private void addMember(
      LinkedHashMap<String, LinkedHashMap<String, Member>> members,
      Member member, String sig) {
    String fullSig = getJsniSignature(member);
    LinkedHashMap<String, Member> membersWithSig = members.get(sig);
    if (membersWithSig == null) {
      membersWithSig = new LinkedHashMap<String, Member>();
      members.put(sig, membersWithSig);
    }
    membersWithSig.put(fullSig, member);
  }

  private void addMemberIfUnique(String name, List<Member> membersForName) {
    if (membersForName.size() == 1) {
      memberById.add(membersForName.get(0));
      memberIdByName.put(
          StringInterner.get().intern(name), memberById.size() - 1);
    }
  }

  private List<Member> filterOutSyntheticMembers(Collection<Member> members) {
    List<Member> nonSynth = new ArrayList<Member>();
    for (Member member : members) {
      if (!member.isSynthetic()) {
        nonSynth.add(member);
      }
    }
    return nonSynth;
  }

  private LinkedHashMap<String, LinkedHashMap<String, Member>> findMostDerivedMembers(
      Class<?> targetClass, boolean addConstructors) {
    LinkedHashMap<String, LinkedHashMap<String, Member>> members = new LinkedHashMap<String, LinkedHashMap<String, Member>>();
    findMostDerivedMembers(members, targetClass, addConstructors);
    return members;
  }

  /**
   * For each available JSNI reference, find the most derived field or method
   * that matches it. For wildcard references, there will be more than one of
   * them, one for each signature matched.
   */
  private void findMostDerivedMembers(
      LinkedHashMap<String, LinkedHashMap<String, Member>> members,
      Class<?> targetClass, boolean addConstructors) {
    /*
     * Analyze superclasses and interfaces first. More derived members will thus
     * be seen later.
     */
    Class<?> superclass = targetClass.getSuperclass();
    if (superclass != null) {
      findMostDerivedMembers(members, superclass, false);
    }
    for (Class<?> intf : targetClass.getInterfaces()) {
      findMostDerivedMembers(members, intf, false);
    }

    if (addConstructors) {
      for (Constructor<?> ctor : targetClass.getDeclaredConstructors()) {
        ctor.setAccessible(true);
        addMember(members, ctor, getJsniSignature(ctor));
      }
    }

    // Get the methods on this class/interface.
    for (Method method : targetClass.getDeclaredMethods()) {
      method.setAccessible(true);
      addMember(members, method, getJsniSignature(method));
    }

    // Get the fields on this class/interface.
    Field[] fields = targetClass.getDeclaredFields();
    for (Field field : fields) {
      field.setAccessible(true);
      addMember(members, field, field.getName());
    }

    // Add a synthetic field to access class literals from JSNI
    addMember(members, new SyntheticClassMember(targetClass), "class");
  }

  private String getJsniSignature(Member member) {
    String name;
    Class<?>[] paramTypes;

    if (member instanceof Field) {
      return member.getName();
    } else if (member instanceof SyntheticClassMember) {
      return member.getName();
    } else if (member instanceof Method) {
      name = member.getName();
      paramTypes = ((Method) member).getParameterTypes();
    } else if (member instanceof Constructor<?>) {
      name = "new";
      paramTypes = ((Constructor<?>) member).getParameterTypes();
    } else {
      throw new RuntimeException("Unexpected member type "
          + member.getClass().getName());
    }

    StringBuffer sb = new StringBuffer();
    sb.append(name);
    sb.append("(");
    for (int i = 0; i < paramTypes.length; ++i) {
      Class<?> type = paramTypes[i];
      String typeSig = getTypeSig(type);
      sb.append(typeSig);
    }
    sb.append(")");

    String mangledName = StringInterner.get().intern(sb.toString());

    return mangledName;
  }

  /*
   * TODO(jat): generics?
   */
  private String getTypeSig(Class<?> type) {
    if (type.isArray()) {
      return "[" + getTypeSig(type.getComponentType());
    }

    if (type.isPrimitive()) {
      if (type.equals(int.class)) {
        return "I";
      } else if (type.equals(boolean.class)) {
        return "Z";
      } else if (type.equals(char.class)) {
        return "C";
      } else if (type.equals(long.class)) {
        return "J";
      } else if (type.equals(short.class)) {
        return "S";
      } else if (type.equals(float.class)) {
        return "F";
      } else if (type.equals(double.class)) {
        return "D";
      } else if (type.equals(byte.class)) {
        return "B";
      } else {
        throw new RuntimeException("Unexpected primitive type: "
            + type.getName());
      }
    } else {
      StringBuffer sb = new StringBuffer();
      sb.append("L");
      sb.append(type.getName().replace('.', '/'));
      sb.append(";");
      return sb.toString();
    }
  }

  private void lazyInitTargetMembers() {
    if (memberById == null) {
      memberById = new ArrayList<Member>();
      memberById.add(null); // 0 is reserved; it's magic on Win32
      memberIdByName = new HashMap<String, Integer>();

      LinkedHashMap<String, LinkedHashMap<String, Member>> members = findMostDerivedMembers(
          cls, true);
      for (Entry<String, LinkedHashMap<String, Member>> entry : members.entrySet()) {
        String name = entry.getKey();

        List<Member> membersForName = new ArrayList<Member>(
            entry.getValue().values());
        addMemberIfUnique(name, membersForName); // backward compatibility
        addMemberIfUnique(name, filterOutSyntheticMembers(membersForName));
      }
    }
  }
}
