// 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.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.gerrit.common.Nullable;
import java.util.ArrayList;
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 ImmutableList<Block> parse(@Nullable String source) {
    if (isNullOrEmpty(source)) {
      return ImmutableList.of();
    }

    ImmutableList.Builder<Block> result = ImmutableList.builder();
    for (String p : Splitter.on("\n\n").split(source)) {
      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.build();
  }

  /**
   * 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, ImmutableList.Builder<Block> out) {
    Block block = null;
    StringBuilder textBuilder = null;
    boolean inList = false;
    boolean inParagraph = false;

    for (String line : Splitter.on('\n').split(p)) {
      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* ");
  }
}
