// Copyright (C) 2017 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.googlesource.gerrit.plugins.findowners;

import com.google.common.flogger.FluentLogger;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.permissions.PermissionBackend;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parse lines in an OWNERS file and put them into an OwnersDb. One Parser object should be created
 * to parse only one OWNERS file. It keeps permissionBackend, readFiles, repoManager, project,
 * branch, and filePath of the OWNERS file so it can find files that are included by OWNERS.
 *
 * <p>The usage pattern is:
 *
 * <pre>
 *   Parser parser = new Parser(permissionBackend, readFiles, repoManager, project, branch, repoFilePath);
 *   String content = OwnersDb.getRepoFile(permissionBackend, readFiles, repoManager, null, null,
 *                                         project, branch, repoFilePath, logs);
 *   Parser.Result result = parser.parseFile(dirPath, content);
 * </pre>
 *
 * <p>OWNERS file syntax, semantics, and examples are included in syntax.md.
 */
class Parser {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  // Artifical owner token for "set noparent" when used in per-file.
  protected static final String TOK_SET_NOPARENT = "set noparent";

  // Globs and emails are separated by commas with optional spaces around a comma.
  protected static final String COMMA = "[\\s]*,[\\s]*"; // used in unit tests

  // Separator for project and file paths in an include line.
  private static final String COLON = "[\\s]*:[\\s]*"; // project:file

  private static final String BOL = "^[\\s]*"; // begin-of-line
  private static final String EOL = "[\\s]*(#.*)?$"; // end-of-line
  private static final String GLOB = "[^\\s,=]+"; // a file glob

  // TODO: have a more precise email address pattern.
  private static final String EMAIL_OR_STAR = "([^\\s<>@,]+@[^\\s<>@#,]+|\\*)";
  private static final String EMAIL_LIST =
      "(" + EMAIL_OR_STAR + "(" + COMMA + EMAIL_OR_STAR + ")*)";

  // A Gerrit project name followed by a colon and optional spaces.
  private static final String PROJECT_NAME = "([^\\s:]+" + COLON + ")?";

  // A relative or absolute file path name without any colon or space character.
  private static final String FILE_PATH = "([^\\s:#]+)";

  private static final String PROJECT_AND_FILE = PROJECT_NAME + FILE_PATH;

  private static final String SET_NOPARENT = "set[\\s]+noparent";

  private static final String FILE_DIRECTIVE = "file:[\\s]*" + PROJECT_AND_FILE;
  private static final String INCLUDE_OR_FILE = "(file:[\\s]*|include[\\s]+)";

  // Simple input lines with 0 or 1 sub-pattern.
  private static final Pattern PAT_COMMENT = Pattern.compile(BOL + EOL);
  private static final Pattern PAT_EMAIL = Pattern.compile(BOL + EMAIL_OR_STAR + EOL);
  private static final Pattern PAT_INCLUDE =
      Pattern.compile(BOL + INCLUDE_OR_FILE + PROJECT_AND_FILE + EOL);
  private static final Pattern PAT_NO_PARENT = Pattern.compile(BOL + SET_NOPARENT + EOL);

  // Patterns to match trimmed globs, emails, and set noparent in per-file lines.
  private static final Pattern PAT_PER_FILE_OWNERS =
      Pattern.compile("^(" + EMAIL_LIST + "|" + SET_NOPARENT + "|" + FILE_DIRECTIVE + ")$");
  private static final Pattern PAT_GLOBS =
      Pattern.compile("^(" + GLOB + "(" + COMMA + GLOB + ")*)$");
  // PAT_PER_FILE matches a line to two groups: (1) globs, (2) emails
  // Trimmed 1st group should match PAT_GLOBS;
  // trimmed 2nd group should match PAT_PER_FILE_OWNERS.
  private static final Pattern PAT_PER_FILE =
      Pattern.compile(BOL + "per-file[\\s]+([^=#]+)=[\\s]*([^#]+)" + EOL);
  // Fetch the include/file part of a line with correct syntax.
  private static final Pattern PAT_INCLUDE_OR_FILE =
      Pattern.compile("^.*(" + INCLUDE_OR_FILE + PROJECT_AND_FILE + ")" + EOL);

  // A parser keeps current permissionBackend, readFiles, repoManager, project, branch,
  // included file path, and debug/trace logs.
  private final PermissionBackend permissionBackend;
  private final Map<String, String> readFiles;
  private final GitRepositoryManager repoManager;
  private final String branch; // All owners files are read from the same branch.
  private final IncludeStack stack; // a stack of including files.
  private final List<String> logs; // Keeps debug/trace messages.
  private final Map<String, Result> savedResults; // projectName:filePath => Parser.Result

  static class IncludeStack {
    Deque<String> projectName; // project/repository name of included file
    Deque<String> filePath; // absolute or relative path of included file
    Set<String> allFiles; // to detect recursive inclusion quickly

    IncludeStack(String project, String file) {
      projectName = new ArrayDeque<>();
      filePath = new ArrayDeque<>();
      allFiles = new HashSet<>();
      push(project, file);
    }

    void push(String project, String file) {
      projectName.push(project);
      filePath.push(file);
      allFiles.add(getFileKey(project, file));
    }

    void pop() {
      allFiles.remove(getFileKey(currentProject(), currentFile()));
      projectName.pop();
      filePath.pop();
    }

    String currentProject() {
      return projectName.peek();
    }

    String currentFile() {
      return filePath.peek();
    }

    boolean contains(String project, String file) {
      return allFiles.contains(getFileKey(project, file));
    }
  }

  // For simple unit tests without a repository.
  Parser(String project, String branch, String file) {
    this(null, null, null, project, branch, file, new ArrayList<>());
  }

  Parser(
      PermissionBackend permissionBackend,
      Map<String, String> readFiles,
      GitRepositoryManager repoManager,
      String project,
      String branch,
      String file) {
    this(permissionBackend, readFiles, repoManager, project, branch, file, new ArrayList<>());
  }

  Parser(
      PermissionBackend permissionBackend,
      Map<String, String> readFiles,
      GitRepositoryManager repoManager,
      String project,
      String branch,
      String file,
      List<String> logs) {
    this.permissionBackend = permissionBackend;
    this.readFiles = readFiles;
    this.repoManager = repoManager;
    this.branch = branch;
    this.logs = logs;
    stack = new IncludeStack(project, normalizedRepoDirFilePath(".", file));
    savedResults = new HashMap<>();
  }

  static boolean isComment(String line) {
    return PAT_COMMENT.matcher(line).matches();
  }

  static boolean isInclude(String line) {
    return PAT_INCLUDE.matcher(line).matches();
  }

  static boolean isGlobs(String line) {
    return PAT_GLOBS.matcher(line).matches();
  }

  static boolean isNoParent(String line) {
    return PAT_NO_PARENT.matcher(line).matches();
  }

  static String parseEmail(String line) {
    Matcher m = Parser.PAT_EMAIL.matcher(line);
    return m.matches() ? m.group(1).trim() : null;
  }

  static String[] parseInclude(String project, String line) {
    Matcher m = Parser.PAT_INCLUDE.matcher(line);
    if (!m.matches()) {
      return null;
    }
    String keyword = m.group(1).trim();
    if (keyword.equals("file:")) {
      keyword = "file";
    }
    String projectName = m.group(2);
    if (projectName != null && projectName.length() > 1) {
      // PROJECT_NAME ends with ':'
      projectName = projectName.split(COLON, -1)[0].trim();
    } else {
      projectName = project; // default project name
    }
    return new String[] {keyword, projectName, m.group(3).trim()};
  }

  static String removeExtraSpaces(String s) {
    return s.trim().replaceAll("[\\s]+", " ").replaceAll("[\\s]*:[\\s]*", ":");
  }

  static String[] parsePerFile(String line) {
    Matcher m = PAT_PER_FILE.matcher(line);
    if (!m.matches()
        || !isGlobs(m.group(1).trim())
        || !PAT_PER_FILE_OWNERS.matcher(m.group(2).trim()).matches()) {
      return null;
    }
    return new String[] {removeExtraSpaces(m.group(1)), removeExtraSpaces(m.group(2))};
  }

  static String[] parsePerFileOwners(String line) {
    String[] globsAndOwners = parsePerFile(line);
    return (globsAndOwners != null) ? globsAndOwners[1].split(COMMA, -1) : null;
  }

  static String getIncludeOrFile(String line) {
    Matcher m = PAT_INCLUDE_OR_FILE.matcher(line);
    return m.matches() ? removeExtraSpaces(m.group(1)) : "";
  }

  static class Result {
    boolean stopLooking; // if this file contains set noparent
    Set<String> warnings; // unique warning messages
    Set<String> errors; // unique error messages
    Map<String, Set<String>> owner2paths; // maps from owner email to pathGlobs
    Set<String> noParentGlobs; // per-file dirpath+glob with "set noparent"

    Result() {
      stopLooking = false;
      warnings = new HashSet<>();
      errors = new HashSet<>();
      owner2paths = new HashMap<>();
      noParentGlobs = new HashSet<>();
    }

    void append(Result r, String dir, boolean addAll) {
      // addAll is true when the Result is from an include statements.
      // It is false for the included result of "file:" directive, which
      // only collects owner emails, not per-file or set noparent statement.
      warnings.addAll(r.warnings);
      errors.addAll(r.errors);
      if (addAll) {
        stopLooking = stopLooking || r.stopLooking;
        for (String glob : r.noParentGlobs) {
          noParentGlobs.add(dir + glob);
        }
      }
      for (String key : r.owner2paths.keySet()) {
        for (String path : r.owner2paths.get(key)) {
          // In an included file, top-level owener emails have empty dir path.
          if (path.isEmpty() || addAll) {
            Util.addToMap(owner2paths, key, dir + path);
          }
        }
      }
    }
  }

  /**
   * Parse given lines of an OWNERS files; return parsed Result. It can recursively call itself to
   * parse included files.
   *
   * @param dir is the directory that contains "changed files" of a CL, not necessarily the OWNERS
   *     or included file directory. "owners" found in lines control changed files in 'dir'. 'dir'
   *     ends with '/' or is empty when parsing an included file.
   * @param lines are the source lines of the file to be parsed.
   * @return the parsed data
   */
  Result parseFile(String dir, String[] lines) {
    Result result = new Result();
    int n = 0;
    for (String line : lines) {
      parseLine(result, dir, line, ++n);
    }
    return result;
  }

  Result parseFile(String dir, String content) {
    return parseFile(dir, content.split("\\R"));
  }

  private String normalizedRepoDirFilePath(String dir, String path) {
    try {
      return Util.normalizedRepoDirFilePath(dir, path);
    } catch (IOException e) {
      String msg = "Fail to normalized path " + dir + " / " + path;
      logger.atSevere().withCause(e).log("%s", msg);
      logs.add(msg + ":" + e.getMessage());
      return dir + "/" + path;
    }
  }

  /**
   * Parse a line in OWNERS file and add parsed info into result. This function should be called
   * only by parseFile and Parser unit tests.
   *
   * @param result a Result object to keep parsed info.
   * @param dir the path to OWNERS file directory.
   * @param line the source line.
   * @param num the line number.
   */
  void parseLine(Result result, String dir, String line, int num) {
    String email;
    String[] globsAndOwners;
    String[] parsedKPF; // parsed keyword, projectName, filePath
    if (isNoParent(line)) {
      result.stopLooking = true;
    } else if (isComment(line)) {
      // ignore comment and empty lines.
    } else if ((email = parseEmail(line)) != null) {
      Util.addToMap(result.owner2paths, email, dir); // here dir is not a glob
    } else if ((globsAndOwners = parsePerFile(line)) != null) {
      String[] dirGlobs = globsAndOwners[0].split(COMMA, -1);
      String directive = globsAndOwners[1];
      if (directive.equals(Parser.TOK_SET_NOPARENT)) {
        // per-file globs = set noparent
        for (String glob : dirGlobs) {
          result.noParentGlobs.add(dir + glob);
        }
      } else {
        List<String> ownerEmails;
        if ((parsedKPF = parseInclude(stack.currentProject(), directive)) == null) {
          // per-file globs = ownerEmails
          ownerEmails = Arrays.asList(directive.split(COMMA, -1));
        } else {
          // per-file globs = file: projectFile
          ownerEmails = new ArrayList<>();
          Result r = new Result();
          includeFile(r, "", num, parsedKPF, false);
          for (String key : r.owner2paths.keySet()) {
            for (String path : r.owner2paths.get(key)) {
              if (path.isEmpty()) {
                ownerEmails.add(key);
                break;
              }
            }
          }
        }
        for (String glob : dirGlobs) {
          for (String owner : ownerEmails) {
            Util.addToMap(result.owner2paths, owner, dir + glob);
          }
        }
      }
    } else if ((parsedKPF = parseInclude(stack.currentProject(), line)) != null) {
      includeFile(result, dir, num, parsedKPF, parsedKPF[0].equals("include"));
    } else {
      result.errors.add(errorMsg(stack.currentFile(), num, "ignored unknown line", line));
    }
  }

  /**
   * Find and parse an included file and append data to the 'result'. For an 'include' statement,
   * parsed data is all appended to the given result parameter. For a 'file:' statement or
   * directive, only owner emails are appended. If the project+file name is found in the stored
   * result set, the stored result is reused. The inclusion is skipped if the to be included file is
   * already on the including file stack.
   *
   * @param result to where the included file data should be added.
   * @param dir the including file's directory or glob.
   * @param num source code line number
   * @param parsedKPF the parsed line of include or file directive.
   * @param addAll to add all parsed data into result or not.
   */
  private void includeFile(Result result, String dir, int num, String[] parsedKPF, boolean addAll) {
    String keyword = parsedKPF[0];
    String project = parsedKPF[1];
    String file = parsedKPF[2];
    String includeKPF = keyword + ":" + getFileKey(project, file);
    // Like C/C++ #include, when f1 includes f2 with a relative file path,
    // use f1's directory, not 'dir', as the base for relative path.
    // 'dir' is the directory of OWNERS file, which might include f1 indirectly.
    String repoFile = normalizedRepoDirFilePath(Util.getParentDir(stack.currentFile()), file);
    if (stack.contains(project, repoFile)) {
      logs.add("parseLine:errorRecursion:" + includeKPF);
      result.errors.add(errorMsg(stack.currentFile(), num, "recursive include", includeKPF));
      return;
    }
    String savedResultKey = getFileKey(project, repoFile);
    Result includedFileResult = savedResults.get(savedResultKey);
    if (null != includedFileResult) {
      logs.add("parseLine:useSaved:" + includeKPF);
    } else {
      stack.push(project, repoFile);
      logs.add("parseLine:" + includeKPF);
      String content =
          OwnersDb.getRepoFile(
              permissionBackend,
              readFiles,
              repoManager,
              null,
              null,
              project,
              branch,
              repoFile,
              logs);
      if (content != null && !content.isEmpty()) {
        includedFileResult = parseFile("", content);
      } else {
        logs.add("parseLine:" + keyword + ":()");
        includedFileResult = new Result();
      }
      stack.pop();
      savedResults.put(savedResultKey, includedFileResult);
    }
    result.append(includedFileResult, dir, addAll);
  }

  // Build a readable key or output string for a (project, file) pair.
  static String getFileKey(String project, String file) {
    return project + ":" + file;
  }

  // Build a readable key or output string for a (project, branch, file) tuple.
  static String getFileKey(String project, String branch, String file) {
    return project + ":" + branch + ":" + file;
  }

  private static String createMsgLine(String prefix, String file, int n, String msg, String line) {
    return prefix + file + ":" + n + ": " + msg + ": [" + line + "]";
  }

  static String errorMsg(String file, int n, String msg, String line) {
    return createMsgLine("Error: ", file, n, msg, line);
  }

  static String warningMsg(String file, int n, String msg, String line) {
    return createMsgLine("Warning: ", file, n, msg, line);
  }
}
