/*
 * Copyright 2011 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.client.impl;

import com.google.gwt.autobean.shared.AutoBeanVisitor.CollectionPropertyContext;
import com.google.gwt.autobean.shared.AutoBeanVisitor.MapPropertyContext;
import com.google.gwt.autobean.shared.AutoBeanVisitor.ParameterizationVisitor;
import com.google.gwt.autobean.shared.AutoBeanVisitor.PropertyContext;
import com.google.gwt.core.client.JavaScriptObject;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Provides base methods for generated implementations of PropertyContext.
 */
public final class ClientPropertyContext implements PropertyContext,
    CollectionPropertyContext, MapPropertyContext {

  /**
   * A reference to an instance setter method.
   */
  public static final class Setter extends JavaScriptObject {
    /**
     * Create a trivial Setter that calls {@link Map#put(Object, Object)}.
     */
    public static native Setter mapSetter(Map<String, Object> values, String key) /*-{
      return function(value) {
        values.@java.util.Map::put(*)(key, value);
      };
    }-*/;

    protected Setter() {
    }

    public native void call(Object instance, Object value) /*-{
      this.call(instance, value);
    }-*/;
  }

  private final Object instance;
  private final int[] paramCounts;
  private final Class<?>[] paramTypes;
  private final Setter setter;
  private final Class<?> simpleType;

  public ClientPropertyContext(Object instance, Setter setter, Class<?> type) {
    this.instance = instance;
    this.setter = setter;
    this.simpleType = type;
    this.paramTypes = null;
    this.paramCounts = null;
  }

  public ClientPropertyContext(Object instance, Setter setter,
      Class<?>[] types, int[] paramCounts) {
    this.instance = instance;
    this.setter = setter;
    this.simpleType = null;
    this.paramTypes = types;
    this.paramCounts = paramCounts;

    /*
     * Verify input arrays of same length and that the total parameter count,
     * plus one for the root type, equals the total number of types passed in.
     */
    if (ClientPropertyContext.class.desiredAssertionStatus()) {
      assert types.length == paramCounts.length : "Length mismatch "
          + types.length + " != " + paramCounts.length;
      int count = 1;
      for (int i = 0, j = paramCounts.length; i < j; i++) {
        count += paramCounts[i];
      }
      assert count == types.length : "Mismatch in total parameter count "
          + count + " != " + types.length;
    }
  }

  public void accept(ParameterizationVisitor visitor) {
    traverse(visitor, 0);
  }

  public boolean canSet() {
    return setter != null;
  }

  public Class<?> getElementType() {
    if (paramTypes == null || paramTypes.length < 2) {
      return null;
    }
    if (List.class.equals(paramTypes[0]) || Set.class.equals(paramTypes[0])) {
      return paramTypes[1];
    }
    return null;
  }

  public Class<?> getKeyType() {
    if (paramTypes == null || paramTypes.length < 3) {
      return null;
    }
    if (Map.class.equals(paramTypes[0])) {
      return paramTypes[1];
    }
    return null;
  }

  public Class<?> getType() {
    return simpleType == null ? paramTypes[0] : simpleType;
  }

  public Class<?> getValueType() {
    if (paramTypes == null || paramTypes.length < 3) {
      return null;
    }
    if (Map.class.equals(paramTypes[0])) {
      return paramTypes[2];
    }
    return null;
  }

  public void set(Object value) {
    setter.call(instance, value);
  }

  private int traverse(ParameterizationVisitor visitor, int count) {
    if (simpleType != null) {
      visitor.visitType(simpleType);
      visitor.endVisitType(simpleType);
      return 0;
    }

    Class<?> type = paramTypes[count];
    int paramCount = paramCounts[count];
    ++count;
    if (visitor.visitType(type)) {
      for (int i = 0; i < paramCount; i++) {
        if (visitor.visitParameter()) {
          count = traverse(visitor, count);
        }
        visitor.endVisitParameter();
      }
    }
    visitor.endVisitType(type);
    return count;
  }
}
