// Copyright 2014 The Bazel Authors. 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.devtools.build.docgen;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.devtools.build.lib.analysis.ConfiguredRuleClassProvider;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import javax.annotation.Nullable;

/**
 * A helper class to read and process documentations for rule classes and attributes
 * from exactly one java source file.
 */
public class SourceFileReader {

  private Collection<RuleDocumentation> ruleDocEntries;
  private ListMultimap<String, RuleDocumentationAttribute> attributeDocEntries;
  private final ConfiguredRuleClassProvider ruleClassProvider;
  private final String javaSourceFilePath;

  public SourceFileReader(
      ConfiguredRuleClassProvider ruleClassProvider, String javaSourceFilePath) {
    this.ruleClassProvider = ruleClassProvider;
    this.javaSourceFilePath = javaSourceFilePath;
  }

  /**
   * The handler class of the line read from the text file.
   */
  public abstract static class ReadAction {

    // Text file line indexing starts from 1
    private int lineCnt = 1;

    protected abstract void readLineImpl(String line)
        throws BuildEncyclopediaDocException, IOException;

    protected int getLineCnt() {
      return lineCnt;
    }

    public void readLine(String line)
        throws BuildEncyclopediaDocException, IOException {
      readLineImpl(line);
      lineCnt++;
    }
  }

  private static final String LS = DocgenConsts.LS;

  /**
   * Reads the attribute and rule documentation present in the file represented by
   * SourceFileReader.javaSourceFilePath. The rule doc variables are added to the rule
   * documentation (which therefore must be defined in the same file). The attribute docs are
   * stored in a different class member, so they need to be handled outside this method.
   */
  public void readDocsFromComments() throws BuildEncyclopediaDocException, IOException {
    final Map<String, RuleDocumentation> docMap = new HashMap<>();
    final List<RuleDocumentationVariable> docVariables = new LinkedList<>();
    final ListMultimap<String, RuleDocumentationAttribute> docAttributes =
        LinkedListMultimap.create();
    readTextFile(
        javaSourceFilePath,
        new ReadAction() {

          private boolean inBlazeRuleDocs = false;
          private boolean inBlazeRuleVarDocs = false;
          private boolean inBlazeAttributeDocs = false;
          private boolean inFamilySummary = false;
          private StringBuilder sb = new StringBuilder();
          private String ruleName;
          private String familySummary = "";
          private String ruleType;
          private String ruleFamily;
          private String variableName;
          private String attributeName;
          private ImmutableSet<String> flags;
          private int startLineCnt;

          @Override
          public void readLineImpl(String line) throws BuildEncyclopediaDocException {
            // TODO(bazel-team): check if copy paste code can be reduced using inner classes
            if (inBlazeRuleDocs) {
              if (DocgenConsts.BLAZE_RULE_END.matcher(line).matches()) {
                endBlazeRuleDoc(docMap);
              } else {
                appendLine(line);
              }
            } else if (inBlazeRuleVarDocs) {
              if (DocgenConsts.BLAZE_RULE_VAR_END.matcher(line).matches()) {
                endBlazeRuleVarDoc(docVariables);
              } else {
                appendLine(line);
              }
            } else if (inBlazeAttributeDocs) {
              if (DocgenConsts.BLAZE_RULE_ATTR_END.matcher(line).matches()) {
                endBlazeAttributeDoc(docAttributes);
              } else {
                appendLine(line);
              }
            } else if (inFamilySummary) {
              if (DocgenConsts.FAMILY_SUMMARY_END.matcher(line).matches()) {
                endFamilySummary();
              } else {
                appendLine(line);
              }
            }
            Matcher familySummaryStartMatcher = DocgenConsts.FAMILY_SUMMARY_START.matcher(line);
            Matcher ruleStartMatcher = DocgenConsts.BLAZE_RULE_START.matcher(line);
            Matcher ruleVarStartMatcher = DocgenConsts.BLAZE_RULE_VAR_START.matcher(line);
            Matcher ruleAttrStartMatcher = DocgenConsts.BLAZE_RULE_ATTR_START.matcher(line);
            if (familySummaryStartMatcher.find()) {
              startFamilySummary();
            } else if (ruleStartMatcher.find()) {
              startBlazeRuleDoc(line, ruleStartMatcher);
            } else if (ruleVarStartMatcher.find()) {
              startBlazeRuleVarDoc(ruleVarStartMatcher);
            } else if (ruleAttrStartMatcher.find()) {
              startBlazeAttributeDoc(line, ruleAttrStartMatcher);
            }
          }

          private void appendLine(String line) {
            // Add another line of html code to the building rule documentation
            // Removing whitespace and java comment asterisk from the beginning of the line
            sb.append(line.replaceAll("^[\\s]*\\*", "") + LS);
          }

          private void startBlazeRuleDoc(String line, Matcher matcher)
              throws BuildEncyclopediaDocException {
            sb = new StringBuilder();
            checkDocValidity();
            // Start of a new rule.
            // e.g.: matcher.group(1) = "NAME = cc_binary, TYPE = BINARY, FAMILY = C / C++"
            for (String group : Splitter.on(",").split(matcher.group(1))) {
              List<String> parts = Splitter.on("=").limit(2).splitToList(group);
              boolean good = false;
              if (parts.size() == 2) {
                String key = parts.get(0).trim();
                String value = parts.get(1).trim();
                good = true;
                if (DocgenConsts.META_KEY_NAME.equals(key)) {
                  ruleName = value;
                } else if (DocgenConsts.META_KEY_TYPE.equals(key)) {
                  ruleType = value;
                } else if (DocgenConsts.META_KEY_FAMILY.equals(key)) {
                  ruleFamily = value;
                } else {
                  good = false;
                }
              }
              if (!good) {
                System.err.printf(
                    "WARNING: bad rule definition in line %d: '%s'", getLineCnt(), line);
              }
            }

            startLineCnt = getLineCnt();
            addFlags(line);
            inBlazeRuleDocs = true;
          }

          private void startFamilySummary() {
            sb = new StringBuilder();
            inFamilySummary = true;
          }

          private void endFamilySummary() {
            familySummary = sb.toString();
          }

          private void endBlazeRuleDoc(final Map<String, RuleDocumentation> documentations)
              throws BuildEncyclopediaDocException {
            // End of a rule, create RuleDocumentation object
            documentations.put(
                ruleName,
                new RuleDocumentation(
                    ruleName,
                    ruleType,
                    ruleFamily,
                    sb.toString(),
                    getLineCnt(),
                    javaSourceFilePath,
                    flags,
                    familySummary));
            sb = new StringBuilder();
            inBlazeRuleDocs = false;
          }

          private void startBlazeRuleVarDoc(Matcher matcher) throws BuildEncyclopediaDocException {
            checkDocValidity();
            // Start of a new rule variable
            ruleName = matcher.group(1).replaceAll("[\\s]", "");
            variableName = matcher.group(2).replaceAll("[\\s]", "");
            startLineCnt = getLineCnt();
            inBlazeRuleVarDocs = true;
          }

          private void endBlazeRuleVarDoc(final List<RuleDocumentationVariable> docVariables) {
            // End of a rule, create RuleDocumentationVariable object
            docVariables.add(
                new RuleDocumentationVariable(ruleName, variableName, sb.toString(), startLineCnt));
            sb = new StringBuilder();
            inBlazeRuleVarDocs = false;
          }

          private void startBlazeAttributeDoc(String line, Matcher matcher)
              throws BuildEncyclopediaDocException {
            checkDocValidity();
            // Start of a new attribute
            ruleName = matcher.group(1).replaceAll("[\\s]", "");
            attributeName = matcher.group(2).replaceAll("[\\s]", "");
            startLineCnt = getLineCnt();
            addFlags(line);
            inBlazeAttributeDocs = true;
          }

          private void endBlazeAttributeDoc(
              final ListMultimap<String, RuleDocumentationAttribute> docAttributes) {
            // End of a attribute, create RuleDocumentationAttribute object
            docAttributes.put(
                attributeName,
                RuleDocumentationAttribute.create(
                    ruleClassProvider.getRuleClassDefinition(ruleName).getClass(),
                    attributeName,
                    sb.toString(),
                    startLineCnt,
                    javaSourceFilePath,
                    flags));
            sb = new StringBuilder();
            inBlazeAttributeDocs = false;
          }

          private void addFlags(String line) {
            // Add flags if there's any
            Matcher matcher = DocgenConsts.BLAZE_RULE_FLAGS.matcher(line);
            if (matcher.find()) {
              flags = ImmutableSet.<String>copyOf(matcher.group(1).split(","));
            } else {
              flags = ImmutableSet.<String>of();
            }
          }

          private void checkDocValidity() throws BuildEncyclopediaDocException {
            if (inBlazeRuleDocs || inBlazeRuleVarDocs || inBlazeAttributeDocs) {
              throw new BuildEncyclopediaDocException(
                  javaSourceFilePath,
                  getLineCnt(),
                  "Malformed documentation, #BLAZE_RULE started after another #BLAZE_RULE.");
            }
          }
        });

    // Adding rule doc variables to the corresponding rules
    for (RuleDocumentationVariable docVariable : docVariables) {
      if (docMap.containsKey(docVariable.getRuleName())) {
        docMap.get(docVariable.getRuleName()).addDocVariable(
          docVariable.getVariableName(), docVariable.getValue());
      } else {
        throw new BuildEncyclopediaDocException(javaSourceFilePath, docVariable.getStartLineCnt(),
            String.format("Malformed rule variable #BLAZE_RULE(%s).%s, rule %s not found in file.",
                docVariable.getRuleName(), docVariable.getVariableName(),
                docVariable.getRuleName()));
      }
    }
    ruleDocEntries = docMap.values();
    attributeDocEntries = docAttributes;
  }

  public Collection<RuleDocumentation> getRuleDocEntries() {
    return ruleDocEntries;
  }

  public ListMultimap<String, RuleDocumentationAttribute> getAttributeDocEntries() {
    return attributeDocEntries;
  }

  /**
   * Reads the template file without variable substitution.
   */
  public static String readTemplateContents(String templateFilePath)
      throws BuildEncyclopediaDocException, IOException {
    return readTemplateContents(templateFilePath, null);
  }

  /**
   * Reads a template file and substitutes variables of the format ${FOO}.
   *
   * @param variables keys are the possible variable names, e.g. "FOO", values are the substitutions
   *     (can be null)
   */
  public static String readTemplateContents(String templateFilePath,
      final Map<String, String> variables) throws BuildEncyclopediaDocException, IOException {
    final StringBuilder sb = new StringBuilder();
    readTextFile(templateFilePath, new ReadAction() {
      @Override
      public void readLineImpl(String line) {
        sb.append(expandVariables(line, variables)).append(LS);
      }
    });
    return sb.toString();
  }

  private static String expandVariables(String line, Map<String, String> variables) {
    if (variables == null || line.indexOf("${") == -1) {
      return line;
    }

    for (Map.Entry<String, String> variable : variables.entrySet()) {
      line = line.replace("${" + variable.getKey() + "}", variable.getValue());
    }
    return line;
  }

  @Nullable
  private static BufferedReader createReader(String filePath) throws IOException {
    File file = new File(filePath);
    if (file.exists()) {
      return Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8);
    } else {
      InputStream is = SourceFileReader.class.getResourceAsStream(filePath);
      if (is != null) {
        return new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
      } else {
        return null;
      }
    }
  }

  public static void readTextFile(String filePath, ReadAction action)
      throws BuildEncyclopediaDocException, IOException {
    try (BufferedReader br = createReader(filePath)) {
      if (br != null) {
        String line = null;
        while ((line = br.readLine()) != null) {
          action.readLine(line);
        }
      } else {
        System.out.println("Couldn't find file or resource: " + filePath);
      }
    }
  }
}
