/*
 * 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 java.util.ArrayList;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;

public class NavTree {

  public static void writeNavTree(String dir, String refPrefix) {
    List<Node> children = new ArrayList<Node>();
    for (PackageInfo pkg : Doclava.choosePackages()) {
      children.add(makePackageNode(pkg));
    }
    Node node = new Node("Reference", dir + refPrefix + "packages.html", children, null);

    StringBuilder buf = new StringBuilder();
    if (false) {
      // if you want a root node
      buf.append("[");
      node.render(buf);
      buf.append("]");
    } else {
      // if you don't want a root node
      node.renderChildren(buf);
    }

    Data data = Doclava.makeHDF();
    data.setValue("reference_tree", buf.toString());
    if (refPrefix == "gms-"){
      ClearPage.write(data, "gms_navtree_data.cs", "gms_navtree_data.js");
    } else if (refPrefix == "gcm-"){
      ClearPage.write(data, "gcm_navtree_data.cs", "gcm_navtree_data.js");
    } else {
      ClearPage.write(data, "navtree_data.cs", "navtree_data.js");
    }
  }

  /**
   * Write the YAML formatted navigation tree.
   * @see "http://yaml.org/"
   */
  public static void writeYamlTree(String dir, String fileName){
    Data data = Doclava.makeHDF();
    ClassInfo[] classes = Converter.rootClasses();

    SortedMap<String, Object> sorted = new TreeMap<String, Object>();
    for (ClassInfo cl : classes) {
      if (cl.isHiddenOrRemoved()) {
        continue;
      }
      sorted.put(cl.qualifiedName(), cl);

      PackageInfo pkg = cl.containingPackage();
      String name;
      if (pkg == null) {
        name = "";
      } else {
        name = pkg.name();
      }
      sorted.put(name, pkg);
    }

    data = makeYamlHDF(sorted, "docs.pages", data);
    ClearPage.write(data, "yaml_navtree.cs", Doclava.ensureSlash(dir) + fileName);
  }

  public static Data makeYamlHDF(SortedMap<String, Object> sorted, String base, Data data) {

    String key = "docs.pages.";
    int i = 0;
    for (String s : sorted.keySet()) {
      Object o = sorted.get(s);

      if (o instanceof PackageInfo) {
        PackageInfo pkg = (PackageInfo) o;

        data.setValue("docs.pages." + i + ".id", "" + i);
        data.setValue("docs.pages." + i + ".label", pkg.name());
        data.setValue("docs.pages." + i + ".shortname", "API");
        data.setValue("docs.pages." + i + ".link", pkg.htmlPage());
        data.setValue("docs.pages." + i + ".type", "package");
      } else if (o instanceof ClassInfo) {
        ClassInfo cl = (ClassInfo) o;

       // skip classes that are the child of another class, recursion will handle those.
       if (cl.containingClass() == null){

         data.setValue("docs.pages." + i + ".id", "" + i);
         data = makeYamlHDF(cl, "docs.pages."+i, data);
       }
     }

     i++;
   }
   return data;
 }

 public static Data makeYamlHDF(ClassInfo cl, String base, Data data) {
   data.setValue(base + ".label", cl.name());
   data.setValue(base + ".shortname", cl.name().substring(cl.name().lastIndexOf(".")+1));
   data.setValue(base + ".link", cl.htmlPage());
   data.setValue(base + ".type", cl.kind());

   if (cl.innerClasses().size() > 0){
     int j = 0;
     for (ClassInfo cl2 : cl.innerClasses()){
       data = makeYamlHDF(cl2, base + ".children." + j, data);
       j++;
     }
   }

    return data;
  }
  private static Node makePackageNode(PackageInfo pkg) {
    List<Node> children = new ArrayList<Node>();

    addClassNodes(children, "Annotations", pkg.annotations());
    addClassNodes(children, "Interfaces", pkg.interfaces());
    addClassNodes(children, "Classes", pkg.ordinaryClasses());
    addClassNodes(children, "Enums", pkg.enums());
    addClassNodes(children, "Exceptions", pkg.exceptions());
    addClassNodes(children, "Errors", pkg.errors());

    return new Node(pkg.name(), pkg.htmlPage(), children, pkg.getSince());
  }

  private static void addClassNodes(List<Node> parent, String label, ClassInfo[] classes) {
    List<Node> children = new ArrayList<Node>();

    for (ClassInfo cl : classes) {
      if (cl.checkLevel()) {
        children.add(new Node(cl.name(), cl.htmlPage(), null, cl.getSince()));
      }
    }

    if (children.size() > 0) {
      parent.add(new Node(label, null, children, null));
    }
  }

  private static class Node {
    private String mLabel;
    private String mLink;
    List<Node> mChildren;
    private String mSince;

    Node(String label, String link, List<Node> children, String since) {
      mLabel = label;
      mLink = link;
      mChildren = children;
      mSince = since;
    }

    static void renderString(StringBuilder buf, String s) {
      if (s == null) {
        buf.append("null");
      } else {
        buf.append('"');
        final int N = s.length();
        for (int i = 0; i < N; i++) {
          char c = s.charAt(i);
          if (c >= ' ' && c <= '~' && c != '"' && c != '\\') {
            buf.append(c);
          } else {
            buf.append("\\u");
            for (int j = 0; i < 4; i++) {
              char x = (char) (c & 0x000f);
              if (x >= 10) {
                x = (char) (x - 10 + 'a');
              } else {
                x = (char) (x + '0');
              }
              buf.append(x);
              c >>= 4;
            }
          }
        }
        buf.append('"');
      }
    }

    void renderChildren(StringBuilder buf) {
      List<Node> list = mChildren;
      if (list == null || list.size() == 0) {
        // We output null for no children. That way empty lists here can just
        // be a byproduct of how we generate the lists.
        buf.append("null");
      } else {
        buf.append("[ ");
        final int N = list.size();
        for (int i = 0; i < N; i++) {
          list.get(i).render(buf);
          if (i != N - 1) {
            buf.append(", ");
          }
        }
        buf.append(" ]\n");
      }
    }

    void render(StringBuilder buf) {
      buf.append("[ ");
      renderString(buf, mLabel);
      buf.append(", ");
      renderString(buf, mLink);
      buf.append(", ");
      renderChildren(buf);
      buf.append(", ");
      renderString(buf, mSince);
      buf.append(" ]");
    }
  }
}
