/*
 * Copyright (C) 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.doclava;

import com.google.clearsilver.jsilver.data.Data;
import com.google.doclava.apicheck.ApiCheck;
import com.google.doclava.apicheck.ApiInfo;
import com.google.doclava.apicheck.ApiParseException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * Applies version information to the Doclava class model from apicheck XML files. Sample usage:
 *
 * <pre>
 *   ClassInfo[] classInfos = ...
 *
 *   SinceTagger sinceTagger = new SinceTagger()
 *   sinceTagger.addVersion("frameworks/base/api/1.xml", "product 1.0")
 *   sinceTagger.addVersion("frameworks/base/api/2.xml", "product 1.5")
 *   sinceTagger.tagAll(...);
 * </pre>
 */
public class SinceTagger {

  private final Map<String, String> xmlToName = new LinkedHashMap<String, String>();

  /**
   * Specifies the apicheck XML file and the API version it holds. Calls to this method should be
   * called in order from oldest version to newest.
   */
  public void addVersion(String file, String name) {
    xmlToName.put(file, name);
  }

  public void tagAll(Collection<ClassInfo> classDocs) {
    // read through the XML files in order, applying their since information
    // to the Javadoc models
    for (Map.Entry<String, String> versionSpec : xmlToName.entrySet()) {
      String xmlFile = versionSpec.getKey();
      String versionName = versionSpec.getValue();

      ApiInfo specApi;
      try {
        specApi = new ApiCheck().parseApi(xmlFile);
      } catch (ApiParseException e) {
        StringWriter stackTraceWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stackTraceWriter));
        Errors.error(Errors.BROKEN_SINCE_FILE, (SourcePositionInfo) null,
            "Failed to parse " + xmlFile + " for " + versionName + " since data.\n"
                + stackTraceWriter.toString());
        continue;
      }

      applyVersionsFromSpec(versionName, specApi, classDocs);
    }

    if (!xmlToName.isEmpty()) {
      warnForMissingVersions(classDocs);
    }
  }

  public boolean hasVersions() {
    return !xmlToName.isEmpty();
  }

  /**
   * Writes an index of the version names to {@code data}.
   */
  public void writeVersionNames(Data data) {
    int index = 1;
    for (String version : xmlToName.values()) {
      data.setValue("since." + index + ".name", version);
      index++;
    }
  }

  /**
   * Applies the version information to {@code classDocs} where not already present.
   *
   * @param versionName the version name
   * @param specApi the spec for this version. If a symbol is in this spec, it was present in the
   *        named version
   * @param classDocs the doc model to update
   */
  private void applyVersionsFromSpec(String versionName, ApiInfo specApi,
      Collection<ClassInfo> classDocs) {
    for (ClassInfo classDoc : classDocs) {
      PackageInfo packageSpec
          = specApi.getPackages().get(classDoc.containingPackage().name());

      if (packageSpec == null) {
        continue;
      }

      ClassInfo classSpec = packageSpec.allClasses().get(classDoc.name());

      if (classSpec == null) {
        continue;
      }

      versionPackage(versionName, classDoc.containingPackage());
      versionClass(versionName, classSpec, classDoc);
      versionConstructors(versionName, classSpec, classDoc);
      versionFields(versionName, classSpec, classDoc);
      versionMethods(versionName, classSpec, classDoc);
    }
  }

  /**
   * Applies version information to {@code doc} where not already present.
   */
  private void versionPackage(String versionName, PackageInfo doc) {
    if (doc.getSince() == null) {
      doc.setSince(versionName);
    }
  }

  /**
   * Applies version information to {@code doc} where not already present.
   */
  private void versionClass(String versionName, ClassInfo spec, ClassInfo doc) {
    if (doc.getSince() == null) {
      doc.setSince(versionName);
    }

    // Set deprecated version
    if (doc.isDeprecated() && doc.getDeprecatedSince() == null) {
      if (spec.isDeprecated()) {
        doc.setDeprecatedSince(versionName);
      }
    }
  }

  /**
   * Applies version information from {@code spec} to {@code doc} where not already present.
   */
  private void versionConstructors(String versionName, ClassInfo spec, ClassInfo doc) {
    for (MethodInfo constructor : doc.constructors()) {
      if (constructor.getSince() == null
          && spec.hasConstructor(constructor)) {
        constructor.setSince(versionName);
      }

      // Set deprecated version
      if (constructor.isDeprecated() && constructor.getDeprecatedSince() == null) {
        // Find matching field from API spec
        if (spec.allConstructorsMap().containsKey(constructor.getHashableName())) {
          MethodInfo specConstructor = spec.allConstructorsMap().get(constructor.getHashableName());
          if (specConstructor.isDeprecated()) {
            constructor.setDeprecatedSince(versionName);
          }
        }
      }
    }
  }

  /**
   * Applies version information from {@code spec} to {@code doc} where not already present.
   */
  private void versionFields(String versionName, ClassInfo spec, ClassInfo doc) {
    for (FieldInfo field : doc.fields()) {
      if (field.getSince() == null && (spec.allFields().containsKey(field.name()) ||
                                       spec.allEnums().containsKey(field.name()))) {
        field.setSince(versionName);
      }

      // Set deprecated version
      if (field.isDeprecated() && field.getDeprecatedSince() == null) {
        // Find matching field from API spec
        if (spec.allFields().containsKey(field.name())) {
          FieldInfo specField = spec.allFields().get(field.name());
          if (specField.isDeprecated()) {
            field.setDeprecatedSince(versionName);
          }
        }
      }
    }
  }

  /**
   * Applies version information from {@code spec} to {@code doc} where not already present.
   */
  private void versionMethods(String versionName, ClassInfo spec, ClassInfo doc) {
    for (MethodInfo method : doc.methods()) {

      // Set deprecated version
      if (method.isDeprecated() && method.getDeprecatedSince() == null) {
        // Find matching method from API spec
        if (spec.allMethods().containsKey(method.getHashableName())) {
          MethodInfo specMethod = spec.allMethods().get(method.getHashableName());
          if (specMethod.isDeprecated()) {
            method.setDeprecatedSince(versionName);
          }
        }
      }

      if (method.getSince() != null) {
        continue;
      }

      for (ClassInfo superclass : spec.hierarchy()) {
        if (superclass.allMethods().containsKey(method.getHashableName())) {
          method.setSince(versionName);
          break;
        }
      }
    }
  }

  /**
   * Warns if any symbols are missing version information. When configured properly, this will yield
   * zero warnings because {@code apicheck} guarantees that all symbols are present in the most
   * recent API.
   */
  private void warnForMissingVersions(Collection<ClassInfo> classDocs) {
    for (ClassInfo claz : classDocs) {
      if (!checkLevelRecursive(claz)) {
        continue;
      }

      if (claz.getSince() == null) {
        Errors.error(Errors.NO_SINCE_DATA, claz.position(), "XML missing class "
            + claz.qualifiedName());
      }

      for (FieldInfo field : missingVersions(claz.fields())) {
        Errors.error(Errors.NO_SINCE_DATA, field.position(), "XML missing field "
            + claz.qualifiedName() + "#" + field.name());
      }

      for (MethodInfo constructor : missingVersions(claz.constructors())) {
        Errors.error(Errors.NO_SINCE_DATA, constructor.position(), "XML missing constructor "
            + claz.qualifiedName() + "#" + constructor.getHashableName());
      }

      for (MethodInfo method : missingVersions(claz.methods())) {
        Errors.error(Errors.NO_SINCE_DATA, method.position(), "XML missing method "
            + claz.qualifiedName() + "#" + method.getHashableName());
      }
    }
  }

  /**
   * Returns the DocInfos in {@code all} that are documented but do not have since tags.
   */
  private <T extends MemberInfo> Iterable<T> missingVersions(ArrayList<T> all) {
    List<T> result = Collections.emptyList();
    for (T t : all) {
      // if this member has version info or isn't documented, skip it
      if (t.getSince() != null || t.isHiddenOrRemoved() ||
          !checkLevelRecursive(t.realContainingClass())) {
        continue;
      }

      if (result.isEmpty()) {
        result = new ArrayList<T>(); // lazily construct a mutable list
      }
      result.add(t);
    }
    return result;
  }

  /**
   * Returns true if {@code claz} and all containing classes are documented. The result may be used
   * to filter out members that exist in the API data structure but aren't a part of the API.
   */
  private boolean checkLevelRecursive(ClassInfo claz) {
    for (ClassInfo c = claz; c != null; c = c.containingClass()) {
      if (!c.checkLevel()) {
        return false;
      }
    }
    return true;
  }
}
