/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.trinidadbuild.plugin.faces.generator.component;

import java.io.IOException;

import java.lang.reflect.Modifier;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.maven.plugin.logging.Log;
import org.apache.myfaces.trinidadbuild.plugin.faces.io.PrettyWriter;
import org.apache.myfaces.trinidadbuild.plugin.faces.parse.ComponentBean;
import org.apache.myfaces.trinidadbuild.plugin.faces.parse.PropertyBean;
import org.apache.myfaces.trinidadbuild.plugin.faces.util.FilteredIterator;
import org.apache.myfaces.trinidadbuild.plugin.faces.util.PropertyFilter;
import org.apache.myfaces.trinidadbuild.plugin.faces.util.Util;


public class TrinidadComponentGenerator extends AbstractComponentGenerator
{
  public TrinidadComponentGenerator(Log log, boolean is12)
  {
    super(log, is12);
  }

  protected void addSpecificImports(Set imports, ComponentBean component)
  {
    // FacesBean is always needed to define the TYPE

    imports.add("org.apache.myfaces.trinidad.bean.FacesBean");

    Iterator<PropertyBean> properties = component.properties();
    properties = new FilteredIterator(properties, new NonVirtualFilter());
    // PropertyKey only needed if there are properties
    if (properties.hasNext())
    {
      imports.add("org.apache.myfaces.trinidad.bean.PropertyKey");

      PropertyFilter resolvable = new ResolvableTypeFilter();
      while (properties.hasNext())
      {
        PropertyBean property = properties.next();

        // ComponentUtils only needed for resolvable properties
        if (resolvable.accept(property))
        {
          imports.add("org.apache.myfaces.trinidad.util.ComponentUtils");
        }
        if (property.isNoOp())
        {
          imports.add("org.apache.myfaces.trinidad.logging.TrinidadLogger");
        }
      }
    }
  }

  protected void writeConstructorContent(PrettyWriter out,
                                         ComponentBean component,
                                         int modifiers,
                                         String rendererType) throws IOException
  {
    out.println("super(" + rendererType + ");");
  }

  protected void writePropertyListMethods(PrettyWriter out, PropertyBean property, Collection gnoreList)
  {
    // nothing
  }

  public void writePropertyConstants(
      PrettyWriter out,
      String superclassName,
      ComponentBean component) throws IOException
  {
    out.println("static public final FacesBean.Type TYPE = new FacesBean.Type(");
    out.indent();
    out.println(superclassName + ".TYPE);");
    out.unindent();

    //  component property keys
    Iterator<PropertyBean> properties = component.properties();
    properties = new FilteredIterator(properties, new NonVirtualFilter());
    properties = new FilteredIterator(properties, new NonOverriddenFilter());

    while (properties.hasNext())
    {
      PropertyBean property = properties.next();
      String propName = property.getPropertyName();
      String propKey = Util.getConstantNameFromProperty(propName, "_KEY");
      String propAlias = property.getAliasOf();

      if (property.getDeprecated() != null)
      {
        out.println("@Deprecated");
      }

      out.println("static public final PropertyKey " + propKey + " =");
      out.indent();
      if (propAlias != null)
      {
        String aliasKey = Util.getConstantNameFromProperty(propAlias, "_KEY");
        out.print("TYPE.registerAlias(" + aliasKey + ", \"" + propName + "\");");
      }
      else
      {
        out.print("TYPE.registerKey(\"" + propName + "\"");

        // property class
        String propFullClass = property.getPropertyClass();
        String propClass = Util.getClassFromFullClass(propFullClass);
        if (propClass == null)
        {
          propClass = "String";
        }
        String propDefault = property.getDefaultValue();
        String propMutable = _getPropertyMutable(property);

        if (!"Object".equals(propClass) || propDefault != null)
        {
          // TODO: do not use boxed class here
          String boxedClass = Util.getBoxedClass(propClass);
          out.print(", " + boxedClass + ".class");
        }
        else if (propMutable != null)
        {
          out.print(", Object.class");
        }

        if (propDefault != null)
        {
          if (property.isEnum())
            out.print(", Enum.valueOf(" + propClass + ".class," +
                      convertStringToBoxedLiteral("String", propDefault) +
                      ")");
          else
            out.print(", " + convertStringToBoxedLiteral(propClass, propDefault));
        }
        else if (propMutable != null)
        {
          out.print(", null");
        }

        // property capabilities
        String propCaps = _getPropertyCapabilities(property);

        if (propCaps != null)
          out.print(", " + propCaps);

        if (propMutable != null)
        {
          if (propCaps == null )
            out.print(", 0");

          out.print(", " + propMutable);
        }


        out.println(");");
      }
      out.unindent();
    }
  }

  protected void writePropertyDeclaration(PrettyWriter out, PropertyBean property) throws IOException
  {
    // nothing by default
  }

  /**
   * Whether the getters/setters have the final modifier
   *
   * @return true if the getters/setters are final
   */
  protected boolean isAccessorMethodFinal()
  {
    return true;
  }

  protected void writePropertySetterMethodBody(PrettyWriter out,
                                               PropertyBean property,
                                               String propertyClass) throws IOException
  {
    String propName = property.getPropertyName();
    String propKey = Util.getConstantNameFromProperty(propName, "_KEY");
    String propVar = Util.getVariableFromName(propName);

    if (!property.isNoOp())
    {
      if (Util.isPrimitiveClass(propertyClass))
      {
        out.println("setProperty(" + propKey + ", " +
                  convertVariableToBoxedForm(propertyClass, propVar) +
                  ");");
      }
      else
      {
        out.println("setProperty(" + propKey + ", (" + propVar + "));");
      }
    }
    else
    {
      out.println("TrinidadLogger log = TrinidadLogger.createTrinidadLogger(this.getClass());");
      out.print("log.warning(\"property \\\"" + propName + "\\\" is ");
      out.print("using a no-op implementation. Used in extreme cases when the property value, beyond the default value, results in unwanted behavior.");
      out.println("\");");
    }
  }

  protected void writePropertyGetterMethodBody(
      PrettyWriter out,
      PropertyBean property) throws IOException
  {
    String propName = property.getPropertyName();
    String propertyFullClass = property.getPropertyClass();
    String propertyClass = Util.getClassFromFullClass(propertyFullClass);
    String propKey = Util.getConstantNameFromProperty(propName, "_KEY");

    String resolvableType = resolveType(propertyFullClass);

    if (resolvableType != null)
    {
      // TODO: change signature of ComponentUtils.resolveCharacter
      //       to take Object instead of Character
      if (resolvableType.equals("Character"))
      {
        out.println("return ComponentUtils.resolveCharacter((Character)getProperty(" + propKey + "));");
      }
      else
      {
        // TODO: stop specifying default values in the getters
        String resolveMethod = Util.getPrefixedPropertyName("resolve", resolvableType);
        String propertyDefault = property.getDefaultValue();
        out.print("return ComponentUtils." + resolveMethod + "(getProperty(" + propKey + ")");
        if (propertyDefault != null)
        {
          out.print(", " + Util.convertStringToLiteral(propertyClass,
              propertyDefault));
        }
        out.println(");");
      }
    }
    else
    {
      if (propertyClass.equals("Object"))
      {
        // Cast is not necessary if the property class is Object
        out.println("return getProperty(" + propKey + ");");
      }
      else
      {
        out.println("return (" + propertyClass + ")" +
            "getProperty(" + propKey + ");");
      }
    }
  }

  public void writeStateManagementMethods(PrettyWriter out, ComponentBean component) throws IOException
  {
    // nothing to do here
  }

  public void writePropertyListMethods(
      PrettyWriter out,
      PropertyBean property) throws IOException
  {
    String propName = property.getPropertyName();
    String propKey = Util.getConstantNameFromProperty(propName, "_KEY");
    String propertyClass = property.getPropertyClass();
    if (!"java.util.List".equals(propertyClass))
    {
      getLog().error("Invalid list type: " + propertyClass);
      return;
    }

    // Look for the generic type - if it doesn't exist, then
    // we'll be an Object.
    String[] params = property.getPropertyClassParameters();
    if ((params == null) || (params.length == 0))
      propertyClass = "java.lang.Object";
    else
      propertyClass = params[0];

    propertyClass = Util.getClassFromFullClass(propertyClass);

    String singularName = getSingular(propName);
    String propVar = Util.getVariableFromName(singularName);
    String description = property.getDescription();
    String addMethod = Util.getPrefixedPropertyName("add", singularName);
    String removeMethod = Util.getPrefixedPropertyName("remove", singularName);
    String getMethod = Util.getPrefixedPropertyName("get", propName);

    out.println();
    out.println("/**");
    if (description != null)
    {
      out.println(" * Adds a " + convertMultilineComment(description));
    }
    out.println(" */");
    if (property.getDeprecated() != null)
    {
      out.println("@Deprecated");
    }
    out.println("final public void " + addMethod + "(" + propertyClass + " " +
        propVar + ")");
    out.println("{");
    out.indent();
    out.println("if (" + propVar + " == null)");
    out.println("  throw new NullPointerException();");
    out.println();
    out.println("getFacesBean().addEntry(" + propKey + ", " + propVar + ");");
    out.unindent();
    out.println("}");

    out.println();
    out.println("/**");
    if (description != null)
    {
      out.println(" * Removes a " + convertMultilineComment(description));
    }
    out.println(" */");
    out.println("final public void " + removeMethod + "(" + propertyClass + " " +
        propVar + ")");
    out.println("{");
    out.indent();
    out.println("if (" + propVar + " == null)");
    out.println("  throw new NullPointerException();");
    out.println();
    out.println("getFacesBean().removeEntry(" + propKey + ", " + propVar + ");");
    out.unindent();
    out.println("}");

    out.println();
    out.println("/**");
    if (description != null)
    {
      out.println(" * Gets all " + convertMultilineComment(description));
    }
    out.println(" */");
    if (property.getDeprecated() != null)
    {
      out.println("@Deprecated");
    }
    out.println("final public " + propertyClass + "[] " + getMethod + "()");
    out.println("{");
    out.indent();
    out.println("return (" + propertyClass + "[]) getFacesBean().getEntries(");
    out.println("         " + propKey + ", " + propertyClass + ".class);");
    out.unindent();
    out.println("}");
  }

  @Override
  public void writeOther(PrettyWriter out, ComponentBean component, String overrideClassName) 
  throws IOException
  {
    _writeGetBeanType(out);

    writeConstructor(out, component, overrideClassName, Modifier.PROTECTED);

    _writeTypeLock(out, component);
  }

  protected void _writeGetBeanType(
      PrettyWriter out) throws IOException
  {
    out.println();
    out.println("@Override");
    out.println("protected FacesBean.Type getBeanType()");
    out.println("{");
    out.indent();
    out.println("return TYPE;");
    out.unindent();
    out.println("}");
  }

  private void _writeTypeLock(
      PrettyWriter out, ComponentBean component) throws IOException
  {
    out.println();
    out.println("static");
    out.println("{");
    out.indent();
    String rendererType = component.getRendererType();
    if (rendererType == null)
    {
      out.println("TYPE.lock();");
    }
    else
    {
      String componentFamily = component.findComponentFamily();
      out.println("TYPE.lockAndRegister(\"" + componentFamily + "\"," +
          "\"" + rendererType + "\");");
    }

    out.unindent();
    out.println("}");
  }

  private String _getPropertyMutable(
    PropertyBean property)
  {
    String mutable = property.getMutable();

    if (mutable == null || "immutable".equals(mutable))
      return null;

    if ("rarely".equals(mutable))
    {
      return "PropertyKey.Mutable.RARELY";
    }
    else if ("sometimes".equals(mutable))
    {
      return "PropertyKey.Mutable.SOMETIMES";
    }
    else if ("often".equals(mutable))
    {
      return "PropertyKey.Mutable.OFTEN";
    }

    throw new IllegalArgumentException("unknown mutable property \"" + mutable + "\", supported types are immutable, rarely, sometimes, and often");

  }

  private String _getPropertyCapabilities(
      PropertyBean property)
  {
    List caps = new ArrayList();

    if (property.isMethodBinding() ||
        property.isLiteralOnly())
    {
      caps.add("PropertyKey.CAP_NOT_BOUND");
    }

    if (property.isStateHolder())
    {
      caps.add("PropertyKey.CAP_STATE_HOLDER");
    }

    if (property.isTransient())
    {
      caps.add("PropertyKey.CAP_TRANSIENT");
    }

    if (property.isList())
    {
      caps.add("PropertyKey.CAP_LIST");
    }

    if (caps.isEmpty())
      return null;

    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < caps.size(); i++)
    {
      if (i > 0)
        sb.append(" | ");
      sb.append(caps.get(i));
    }
    return sb.toString();
  }
}
