/*
 * 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.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(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, 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, 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(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;
  }
}
