// 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.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
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;

/**
 * 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 StringBuilder sb = new StringBuilder();
      private String ruleName;
      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);
          }
        }
        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 (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 {
        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 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,
            ruleClassProvider));
        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;
  }

  public static void readTextFile(String filePath, ReadAction action)
      throws BuildEncyclopediaDocException, IOException {
    BufferedReader br = null;
    try {
      File file = new File(filePath);
      if (file.exists()) {
        br = new BufferedReader(new FileReader(file));
      } else {
        InputStream is = SourceFileReader.class.getResourceAsStream(filePath);
        if (is != null) {
          br = new BufferedReader(new InputStreamReader(is));
        }
      }
      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);
      }
    } finally {
      if (br != null) {
        br.close();
      }
    }
  }
}
