// Copyright (C) 2011 The Android Open Source Project
//
// 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.gerrit.server.util;

import java.io.PrintWriter;
import java.util.SortedSet;

public class TreeFormatter {

  public static interface TreeNode {
    public String getDisplayName();
    public boolean isVisible();
    public SortedSet<? extends TreeNode> getChildren();
  }

  public static final String NOT_VISIBLE_NODE = "(x)";

  private static final String NODE_PREFIX = "|-- ";
  private static final String LAST_NODE_PREFIX = "`-- ";
  private static final String DEFAULT_TAB_SEPARATOR = "|";

  private final PrintWriter stdout;
  private String currentTabSeparator = " ";

  public TreeFormatter(final PrintWriter stdout) {
    this.stdout = stdout;
  }

  public void printTree(final SortedSet<? extends TreeNode> rootNodes) {
    if (rootNodes.isEmpty()) {
      return;
    }
    if (rootNodes.size() == 1) {
      printTree(rootNodes.first());
    } else {
      currentTabSeparator = DEFAULT_TAB_SEPARATOR;
      int i = 0;
      final int size = rootNodes.size();
      for (final TreeNode rootNode : rootNodes) {
        final boolean isLastRoot = ++i == size;
        if (isLastRoot) {
          currentTabSeparator = " ";
        }
        printTree(rootNode);
      }
    }
  }

  public void printTree(final TreeNode rootNode) {
    printTree(rootNode, 0, true);
  }

  private void printTree(final TreeNode node, final int level,
      final boolean isLast) {
    printNode(node, level, isLast);
    final SortedSet<? extends TreeNode> childNodes = node.getChildren();
    int i = 0;
    final int size = childNodes.size();
    for (final TreeNode childNode : childNodes) {
      final boolean isLastChild = ++i == size;
      printTree(childNode, level + 1, isLastChild);
    }
  }

  private void printIndention(final int level) {
    if (level > 0) {
      stdout.print(String.format("%-" + 4 * level + "s", currentTabSeparator));
    }
  }

  private void printNode(final TreeNode node, final int level,
      final boolean isLast) {
    printIndention(level);
    stdout.print(isLast ? LAST_NODE_PREFIX : NODE_PREFIX);
    if (node.isVisible()) {
      stdout.print(node.getDisplayName());
    } else {
      stdout.print(NOT_VISIBLE_NODE);
    }
    stdout.print("\n");
  }
}
