/*
 * Copyright 2009 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.uibinder.rebind;

import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dom.client.Element;
import com.google.gwt.uibinder.rebind.model.OwnerField;
import com.google.gwt.user.client.ui.RenderablePanel;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
 * Most of the implementation of {@link FieldWriter}. Subclasses are responsible
 * for {@link FieldWriter#getQualifiedSourceName()} and
 * {@link FieldWriter#getInstantiableType()}.
 */
abstract class AbstractFieldWriter implements FieldWriter {
  private static final String NO_DEFAULT_CTOR_ERROR =
      "%1$s has no default (zero args) constructor. To fix this, you can define"
      + " a @UiFactory method on the UiBinder's owner, or annotate a constructor of %2$s with"
      + " @UiConstructor.";

  private static int nextAttachVar;

  public static String getNextAttachVar() {
    return "attachRecord" + nextAttachVar++;
  }

  private final FieldManager manager;
  private final Set<FieldWriter> needs = new LinkedHashSet<FieldWriter>();
  private final List<String> statements = new ArrayList<String>();
  private final List<String> attachStatements = new ArrayList<String>();
  private final List<String> detachStatements = new ArrayList<String>();

  private final String name;
  private String initializer;
  private boolean written;
  private int buildPrecedence;
  private final MortalLogger logger;
  private final FieldWriterType fieldType;
  private String html;

  public AbstractFieldWriter(FieldManager manager, FieldWriterType fieldType,
      String name, MortalLogger logger) {
    if (name == null) {
      throw new RuntimeException("name cannot be null");
    }
    this.manager = manager;
    this.name = name;
    this.logger = logger;
    this.buildPrecedence = 1;
    this.fieldType = fieldType;
  }

  @Override
  public void addAttachStatement(String format, Object... args) {
    attachStatements.add(String.format(format, args));
  }

  @Override
  public void addDetachStatement(String format, Object... args) {
    detachStatements.add(String.format(format, args));
  }

  @Override
  public void addStatement(String format, Object... args) {
    statements.add(String.format(format, args));
  }

  @Override
  public int getBuildPrecedence() {
    return buildPrecedence;
  }

  @Override
  public FieldWriterType getFieldType() {
    return fieldType;
  }

  public String getHtml() {
    return html + ".asString()";
  }

  public String getInitializer() {
    return initializer;
  }

  @Override
  public String getName() {
    return name;
  }

  @Override
  public String getNextReference() {
    return manager.convertFieldToGetter(name);
  }

  public JType getReturnType(String[] path, MonitoredLogger logger) {
    if (!name.equals(path[0])) {
      throw new RuntimeException(this
          + " asked to evaluate another field's path: " + path[0]);
    }

    List<String> pathList = Arrays.asList(path).subList(1, path.length);
    return getReturnType(getAssignableType(), pathList, logger);
  }

  public String getSafeHtml() {
    return html;
  }

  public void needs(FieldWriter f) {
    needs.add(f);
  }

  @Override
  public void setBuildPrecedence(int precedence) {
    this.buildPrecedence = precedence;
  }

  public void setHtml(String html) {
    this.html = html;
  }

  public void setInitializer(String initializer) {
    this.initializer = initializer;
  }

  @Override
  public String toString() {
    return String.format("[%s %s = %s]", this.getClass().getName(), name,
        initializer);
  }

  public void write(IndentedWriter w) throws UnableToCompleteException {
    if (written) {
      return;
    }

    for (FieldWriter f : needs) {
      f.write(w);
    }

    if (initializer == null) {
      JClassType type = getInstantiableType();
      if (type != null) {
        if ((type.isInterface() == null)
            && (type.findConstructor(new JType[0]) == null)) {
          logger.die(NO_DEFAULT_CTOR_ERROR, type.getQualifiedSourceName(),
              type.getName());
        }
      }
    }

    if (null == initializer) {
      initializer = String.format("(%1$s) GWT.create(%1$s.class)",
          getQualifiedSourceName());
    }

    w.write("%s %s = %s;", getQualifiedSourceName(), name, initializer);

    this.written = true;
  }

  @Override
  public void writeFieldBuilder(IndentedWriter w, int getterCount,
    OwnerField ownerField) {
    if (getterCount > 1) {
      w.write("%s;  // more than one getter call detected. Type: %s, precedence: %s",
            FieldManager.getFieldBuilder(name), getFieldType(), getBuildPrecedence());
      return;
    }

    if (getterCount == 0 && ownerField != null) {
      w.write("%s;  // no getter call detected but must bind to ui:field. "
          + "Type: %s, precedence: %s", FieldManager.getFieldBuilder(name),
          getFieldType(), getBuildPrecedence());
    }
  }

  @Override
  public void writeFieldDefinition(IndentedWriter w, TypeOracle typeOracle,
      OwnerField ownerField, DesignTimeUtils designTime, int getterCount,
      boolean useLazyWidgetBuilders)
      throws UnableToCompleteException {

    JClassType renderablePanelType = typeOracle.findType(
        RenderablePanel.class.getName());
    boolean outputAttachDetachCallbacks = useLazyWidgetBuilders
        && getAssignableType() != null
        && getAssignableType().isAssignableTo(renderablePanelType);

    // Check initializer. Provided value takes precedence over initializer.
    if (ownerField != null && ownerField.isProvided()) {
      initializer = String.format("owner.%s", name);
    } else if (initializer == null) {
      JClassType type = getInstantiableType();
      if (type != null) {
        if ((type.isInterface() == null)
            && (type.findConstructor(new JType[0]) == null)) {
          logger.die(NO_DEFAULT_CTOR_ERROR, type.getQualifiedSourceName(),
              type.getName());
        }
      }
      initializer = String.format("(%1$s) GWT.create(%1$s.class)",
          getQualifiedSourceName());
    }

    w.newline();
    w.write("/**");
    w.write(" * Getter for %s called %s times. Type: %s. Build precedence: %s.",
        name, getterCount, getFieldType(), getBuildPrecedence());
    w.write(" */");
    if (getterCount > 1) {
      w.write("private %1$s %2$s;", getQualifiedSourceName(), name);
    }

    w.write("private %s %s {", getQualifiedSourceName(), FieldManager.getFieldGetter(name));
    w.indent();
    w.write("return %s;", (getterCount > 1) ? name : FieldManager.getFieldBuilder(name));
    w.outdent();
    w.write("}");

    w.write("private %s %s {", getQualifiedSourceName(), FieldManager.getFieldBuilder(name));
    w.indent();

    w.write("// Creation section.");
    if (getterCount > 1) {
      w.write("%s = %s;", name, initializer);
    } else {
      w.write("final %s %s = %s;", getQualifiedSourceName(), name, initializer);
    }
    if (ownerField != null && ownerField.isProvided() && !designTime.isDesignTime()) {
      w.write("assert %1$s != null : \"UiField %1$s with 'provided = true' was null\";", name);
    }

    w.write("// Setup section.");
    for (String s : statements) {
      w.write(s);
    }

    String attachedVar = null;

    if (attachStatements.size() > 0) {
      w.newline();
      w.write("// Attach section.");
      if (outputAttachDetachCallbacks) {
        // TODO(rdcastro): This is too coupled with RenderablePanel.
        // Make this nicer.
        w.write("%s.wrapInitializationCallback = ", getName());
        w.indent();
        w.indent();
        w.write(
            "new com.google.gwt.user.client.Command() {");
        w.outdent();
        w.write("@Override public void execute() {");
        w.indent();
      } else {
        attachedVar = getNextAttachVar();

        JClassType elementType = typeOracle.findType(Element.class.getName());

        String elementToAttach = getInstantiableType().isAssignableTo(elementType)
            ? name : name + ".getElement()";

        w.write("UiBinderUtil.TempAttachment %s = UiBinderUtil.attachToDom(%s);",
                attachedVar, elementToAttach);
      }

      for (String s : attachStatements) {
        w.write(s);
      }

      if (outputAttachDetachCallbacks) {
        w.outdent();
        w.write("}");
        w.outdent();
        w.write("};");
      }
    }

    w.newline();
    // If we forced an attach, we should always detach, regardless of whether
    // there are any detach statements.
    if (attachedVar != null) {
      w.write("// Detach section.");
      w.write("%s.detach();", attachedVar);
    }

    if (detachStatements.size() > 0) {
      if (outputAttachDetachCallbacks) {
        w.write("%s.detachedInitializationCallback = ", getName());
        w.indent();
        w.indent();
        w.write("new com.google.gwt.user.client.Command() {");
        w.outdent();
        w.write("@Override public void execute() {");
        w.indent();
      }

      for (String s : detachStatements) {
        w.write(s);
      }

      if (outputAttachDetachCallbacks) {
        w.outdent();
        w.write("}");
        w.outdent();
        w.write("};");
      }
    }

    if ((ownerField != null) && !ownerField.isProvided()) {
      w.newline();
      w.write("owner.%1$s = %1$s;", name);
    }

    w.newline();
    w.write("return %s;", name);
    w.outdent();
    w.write("}");
  }

  private JMethod findMethod(JClassType type, String methodName) {
    // TODO Move this and getClassHierarchyBreadthFirst to JClassType
    for (JClassType nextType : UiBinderWriter.getClassHierarchyBreadthFirst(type)) {
      try {
        return nextType.getMethod(methodName, new JType[0]);
      } catch (NotFoundException e) {
        /* try parent */
      }
    }
    return null;
  }

  private JType getReturnType(JType type, List<String> path,
      MonitoredLogger logger) {
    // TODO(rjrjr,bobv) This is derived from CssResourceGenerator.validateValue
    // We should find a way share code

    Iterator<String> i = path.iterator();
    while (i.hasNext()) {
      String pathElement = i.next();

      JClassType referenceType = type.isClassOrInterface();
      if (referenceType == null) {
        logger.error("Cannot resolve member " + pathElement
            + " on non-reference type " + type.getQualifiedSourceName());
        return null;
      }

      JMethod m = findMethod(referenceType, pathElement);
      if (m == null) {
        logger.error("Could not find no-arg method named " + pathElement
            + " in type " + type.getQualifiedSourceName());
        return null;
      }

      type = m.getReturnType();
    }
    return type;
  }
}
