// Copyright (C) 2016 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.mail.send;

import static com.google.common.base.Strings.isNullOrEmpty;

import com.google.gerrit.common.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CommentFormatter {
  public enum BlockType {
    LIST,
    PARAGRAPH,
    PRE_FORMATTED,
    QUOTE
  }

  public static class Block {
    public BlockType type;
    public String text;
    public List<String> items; // For the items of list blocks.
    public List<Block> quotedBlocks; // For the contents of quote blocks.
  }

  /**
   * Take a string of comment text that was written using the wiki-Like format and emit a list of
   * blocks that can be rendered to block-level HTML. This method does not escape HTML.
   *
   * <p>Adapted from the {@code wikify} method found in:
   * com.google.gwtexpui.safehtml.client.SafeHtml
   *
   * @param source The raw, unescaped comment in the Gerrit wiki-like format.
   * @return List of block objects, each with unescaped comment content.
   */
  public static List<Block> parse(@Nullable String source) {
    if (isNullOrEmpty(source)) {
      return Collections.emptyList();
    }

    List<Block> result = new ArrayList<>();
    for (String p : source.split("\n\n")) {
      if (isQuote(p)) {
        result.add(makeQuote(p));
      } else if (isPreFormat(p)) {
        result.add(makePre(p));
      } else if (isList(p)) {
        makeList(p, result);
      } else if (!p.isEmpty()) {
        result.add(makeParagraph(p));
      }
    }
    return result;
  }

  /**
   * Take a block of comment text that contains a list and potentially paragraphs (but does not
   * contain blank lines), generate appropriate block elements and append them to the output list.
   *
   * <p>In simple cases, this will generate a single list block. For example, on the following
   * input.
   *
   * <p>* Item one. * Item two. * item three.
   *
   * <p>However, if the list is adjacent to a paragraph, it will need to also generate that
   * paragraph. Consider the following input.
   *
   * <p>A bit of text describing the context of the list: * List item one. * List item two. * Et
   * cetera.
   *
   * <p>In this case, {@code makeList} generates a paragraph block object containing the
   * non-bullet-prefixed text, followed by a list block.
   *
   * <p>Adapted from the {@code wikifyList} method found in:
   * com.google.gwtexpui.safehtml.client.SafeHtml
   *
   * @param p The block containing the list (as well as potential paragraphs).
   * @param out The list of blocks to append to.
   */
  private static void makeList(String p, List<Block> out) {
    Block block = null;
    StringBuilder textBuilder = null;
    boolean inList = false;
    boolean inParagraph = false;

    for (String line : p.split("\n")) {
      if (line.startsWith("-") || line.startsWith("*")) {
        // The next line looks like a list item. If not building a list already,
        // then create one. Remove the list item marker (* or -) from the line.
        if (!inList) {
          if (inParagraph) {
            // Add the finished paragraph block to the result.
            inParagraph = false;
            block.text = textBuilder.toString();
            out.add(block);
          }

          inList = true;
          block = new Block();
          block.type = BlockType.LIST;
          block.items = new ArrayList<>();
        }
        line = line.substring(1).trim();

      } else if (!inList) {
        // Otherwise, if a list has not yet been started, but the next line does
        // not look like a list item, then add the line to a paragraph block. If
        // a paragraph block has not yet been started, then create one.
        if (!inParagraph) {
          inParagraph = true;
          block = new Block();
          block.type = BlockType.PARAGRAPH;
          textBuilder = new StringBuilder();
        } else {
          textBuilder.append(" ");
        }
        textBuilder.append(line);
        continue;
      }

      block.items.add(line);
    }

    if (block != null) {
      out.add(block);
    }
  }

  private static Block makeQuote(String p) {
    String quote = p.replaceAll("\n\\s?>\\s?", "\n");
    if (quote.startsWith("> ")) {
      quote = quote.substring(2);
    } else if (quote.startsWith(" > ")) {
      quote = quote.substring(3);
    }

    Block block = new Block();
    block.type = BlockType.QUOTE;
    block.quotedBlocks = CommentFormatter.parse(quote);
    return block;
  }

  private static Block makePre(String p) {
    Block block = new Block();
    block.type = BlockType.PRE_FORMATTED;
    block.text = p;
    return block;
  }

  private static Block makeParagraph(String p) {
    Block block = new Block();
    block.type = BlockType.PARAGRAPH;
    block.text = p;
    return block;
  }

  private static boolean isQuote(String p) {
    return p.startsWith("> ") || p.startsWith(" > ");
  }

  private static boolean isPreFormat(String p) {
    return p.startsWith(" ") || p.startsWith("\t") || p.contains("\n ") || p.contains("\n\t");
  }

  private static boolean isList(String p) {
    return p.startsWith("- ") || p.startsWith("* ") || p.contains("\n- ") || p.contains("\n* ");
  }
}
