// Copyright 2015 Google Inc. All Rights Reserved.
//
// 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.gitiles.doc;

import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.MultimapBuilder;
import com.google.gitiles.doc.html.HtmlBuilder;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import org.apache.commons.lang3.StringUtils;
import org.commonmark.node.Heading;
import org.commonmark.node.Node;

/** Outputs outline from HeaderNodes in the AST. */
class TocFormatter {
  private final HtmlBuilder html;
  private final int maxLevel;

  private int countH1;
  private List<Heading> outline;
  private Map<Heading, String> ids;

  private int level;

  TocFormatter(HtmlBuilder html, int maxLevel) {
    this.html = html;
    this.maxLevel = maxLevel;
  }

  void setRoot(Node doc) {
    outline = new ArrayList<>();
    ListMultimap<String, TocEntry> entries =
        MultimapBuilder.hashKeys(16).arrayListValues(4).build();
    scan(doc, entries, new ArrayDeque<Heading>());
    ids = generateIds(entries);
  }

  private boolean include(Heading h) {
    if (h.getLevel() == 1) {
      return countH1 > 1;
    }
    return h.getLevel() <= maxLevel;
  }

  String idFromHeader(Heading header) {
    return ids.get(header);
  }

  void format() {
    int startLevel = countH1 > 1 ? 1 : 2;
    level = startLevel;

    html.open("div")
        .attribute("class", "toc")
        .attribute("role", "navigation")
        .open("h2")
        .appendAndEscape("Contents")
        .close("h2")
        .open("div")
        .attribute("class", "toc-aux")
        .open("ul");
    for (Heading header : outline) {
      outline(header);
    }
    while (level >= startLevel) {
      html.close("ul");
      level--;
    }
    html.close("div").close("div");
  }

  private void outline(Heading h) {
    if (!include(h)) {
      return;
    }

    String id = idFromHeader(h);
    if (id == null) {
      return;
    }

    while (level > h.getLevel()) {
      html.close("ul");
      level--;
    }
    while (level < h.getLevel()) {
      html.open("ul");
      level++;
    }

    html.open("li")
        .open("a")
        .attribute("href", "#" + id)
        .appendAndEscape(MarkdownUtil.getInnerText(h))
        .close("a")
        .close("li");
  }

  private void scan(Node node, ListMultimap<String, TocEntry> entries, Deque<Heading> stack) {
    if (node instanceof Heading) {
      scan((Heading) node, entries, stack);
    } else {
      for (Node c = node.getFirstChild(); c != null; c = c.getNext()) {
        scan(c, entries, stack);
      }
    }
  }

  private void scan(Heading header, ListMultimap<String, TocEntry> entries, Deque<Heading> stack) {
    if (header.getLevel() == 1) {
      countH1++;
    }
    while (!stack.isEmpty() && stack.getLast().getLevel() >= header.getLevel()) {
      stack.removeLast();
    }

    NamedAnchor node = findAnchor(header);
    if (node != null) {
      entries.put(node.getName(), new TocEntry(stack, header, false, node.getName()));
      stack.add(header);
      outline.add(header);
      return;
    }

    String title = MarkdownUtil.getInnerText(header);
    if (title != null) {
      String id = idFromTitle(title);
      entries.put(id, new TocEntry(stack, header, true, id));
      stack.add(header);
      outline.add(header);
    }
  }

  private static @Nullable NamedAnchor findAnchor(Node node) {
    for (Node c = node.getFirstChild(); c != null; c = c.getNext()) {
      if (c instanceof NamedAnchor) {
        return (NamedAnchor) c;
      }
      NamedAnchor anchor = findAnchor(c);
      if (anchor != null) {
        return anchor;
      }
    }
    return null;
  }

  private Map<Heading, String> generateIds(ListMultimap<String, TocEntry> entries) {
    ListMultimap<String, TocEntry> tmp =
        MultimapBuilder.hashKeys(entries.size()).arrayListValues(2).build();
    for (Collection<TocEntry> headers : entries.asMap().values()) {
      if (headers.size() == 1) {
        TocEntry entry = Iterables.getOnlyElement(headers);
        tmp.put(entry.id, entry);
        continue;
      }

      // Try to deduplicate by prefixing with text derived from parents.
      for (TocEntry entry : headers) {
        if (!entry.generated) {
          tmp.put(entry.id, entry);
          continue;
        }

        StringBuilder b = new StringBuilder();
        for (Heading p : entry.path) {
          if (p.getLevel() > 1 || countH1 > 1) {
            String text = MarkdownUtil.getInnerText(p);
            if (text != null) {
              b.append(idFromTitle(text)).append('-');
            }
          }
        }
        b.append(idFromTitle(MarkdownUtil.getInnerText(entry.header)));
        entry.id = b.toString();
        tmp.put(entry.id, entry);
      }
    }

    Map<Heading, String> ids = Maps.newHashMapWithExpectedSize(tmp.size());
    for (Collection<TocEntry> headers : tmp.asMap().values()) {
      if (headers.size() == 1) {
        TocEntry entry = Iterables.getOnlyElement(headers);
        ids.put(entry.header, entry.id);
      } else {
        int i = 1;
        for (TocEntry entry : headers) {
          ids.put(entry.header, entry.id + "-" + i++);
        }
      }
    }
    return ids;
  }

  private static class TocEntry {
    final Heading[] path;
    final Heading header;
    final boolean generated;
    String id;

    TocEntry(Deque<Heading> stack, Heading header, boolean generated, String id) {
      this.path = stack.toArray(new Heading[stack.size()]);
      this.header = header;
      this.generated = generated;
      this.id = id;
    }
  }

  private static String idFromTitle(String title) {
    StringBuilder b = new StringBuilder(title.length());
    for (char c : StringUtils.stripAccents(title).toCharArray()) {
      if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) {
        b.append(c);
      } else if (c == ' ') {
        if (b.length() > 0 && b.charAt(b.length() - 1) != '-' && b.charAt(b.length() - 1) != '_') {
          b.append('-');
        }
      } else if (b.length() > 0
          && b.charAt(b.length() - 1) != '-'
          && b.charAt(b.length() - 1) != '_') {
        b.append('_');
      }
    }
    while (b.length() > 0) {
      char c = b.charAt(b.length() - 1);
      if (c == '-' || c == '_') {
        b.setLength(b.length() - 1);
        continue;
      }
      break;
    }
    return b.toString();
  }
}
