// Copyright 2017 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.skylark.skylint;

import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.events.EventKind;
import com.google.devtools.build.lib.syntax.BuildFileAST;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Main class of the linter library.
 *
 * <p>Most users of the linter library should only need to use this class.
 */
public class Linter {
  private static final String PARSE_ERROR_CATEGORY = "parse-error";
  /** Map of all single-file checks and their names. */
  private static final ImmutableMap<String, Check> nameToCheck =
      ImmutableMap.<String, Check>builder()
          .put("bad-operation", BadOperationChecker::check)
          .put("bad-recursive-glob", NativeRecursiveGlobChecker::check)
          .put("control-flow", ControlFlowChecker::check)
          .put("deprecated-api", DeprecatedApiChecker::check)
          .put("docstring", DocstringChecker::check)
          .put("load", LoadStatementChecker::check)
          .put("naming", NamingConventionsChecker::check)
          .put("no-effect", StatementWithoutEffectChecker::check)
          .put("usage", UsageChecker::check)
          .build();
  /** Map of all multi-file checks and their names. */
  private static final ImmutableMap<String, MultiFileCheck> nameToMultiFileCheck =
      ImmutableMap.<String, MultiFileCheck>builder()
          .put("deprecation", DeprecationChecker::check)
          .build();

  /** Function to read files (can be changed for testing). */
  private FileFacade fileFacade = DEFAULT_FILE_FACADE;

  private static final FileFacade DEFAULT_FILE_FACADE =
      new FileFacade() {
        @Override
        public boolean fileExists(Path path) {
          return Files.exists(path);
        }

        @Override
        public byte[] readBytes(Path path) throws IOException {
          return Files.readAllBytes(path);
        }
      };

  private boolean singleFileMode = false;
  private final Set<String> disabledChecks = new LinkedHashSet<>();
  private final Set<String> disabledCategories = new LinkedHashSet<>();

  public Linter setFileContentsReader(FileFacade reader) {
    this.fileFacade = reader;
    return this;
  }

  public Linter disableCheck(String checkName) {
    if (!nameToCheck.containsKey(checkName)) {
      throw new IllegalArgumentException("Unknown check '" + checkName + "' cannot be disabled.");
    }
    disabledChecks.add(checkName);
    return this;
  }

  public Linter disableCategory(String categoryName) {
    disabledCategories.add(categoryName);
    return this;
  }

  /** Disables checks that require analyzing multiple files. */
  public Linter setSingleFileMode() {
    singleFileMode = true;
    return this;
  }

  /**
   * Runs all checks on the given file.
   *
   * @param path path of the file
   * @return list of issues found in that file
   */
  public List<Issue> lint(Path path) throws IOException {
    path = path.toAbsolutePath();
    String content = new String(fileFacade.readBytes(path), StandardCharsets.ISO_8859_1);
    List<Issue> issues = new ArrayList<>();
    BuildFileAST ast =
        BuildFileAST.parseString(
            event -> {
              if (event.getKind() == EventKind.ERROR || event.getKind() == EventKind.WARNING) {
                issues.add(
                    Issue.create(PARSE_ERROR_CATEGORY, event.getMessage(), event.getLocation()));
              }
            },
            content);
    for (Entry<String, Check> entry : nameToCheck.entrySet()) {
      if (disabledChecks.contains(entry.getKey())) {
        continue;
      }
      issues.addAll(entry.getValue().check(ast));
    }
    if (!singleFileMode) {
      for (Entry<String, MultiFileCheck> entry : nameToMultiFileCheck.entrySet()) {
        if (disabledChecks.contains(entry.getKey())) {
          continue;
        }
        issues.addAll(entry.getValue().check(path, ast, fileFacade));
      }
    }
    issues.removeIf(issue -> disabledCategories.contains(issue.category));
    issues.sort(Issue::compareLocation);
    return issues;
  }

  /**
   * Interface with a function that reads a file.
   *
   * <p>This is useful because we can use a fake for testing.
   */
  @FunctionalInterface
  public interface FileFacade {

    /**
     * Reads a file path to bytes.
     *
     * <p>This operation may be repeated for the same file.
     */
    byte[] readBytes(Path path) throws IOException;

    /**
     * Reads a file and parses it to an AST.
     *
     * <p>The default implementation silently ignores syntax errors.
     */
    default BuildFileAST readAst(Path path) throws IOException {
      String contents = new String(readBytes(path), StandardCharsets.ISO_8859_1);
      return BuildFileAST.parseString(event -> {}, contents);
    }

    /**
     * Checks whether a given file exists.
     *
     * <p>The default implementation invokes readBytes and returns false if {@link
     * NoSuchFileException} is thrown, true otherwise.
     */
    default boolean fileExists(Path path) {
      try {
        readBytes(path);
      } catch (NoSuchFileException e) {
        return false;
      } catch (IOException e) {
        // This method shouldn't throw.
      }
      return true;
    }
  }

  /** Allows to invoke a check. */
  @FunctionalInterface
  public interface Check {
    List<Issue> check(BuildFileAST ast);
  }

  /** Allows to invoke a check. */
  @FunctionalInterface
  public interface MultiFileCheck {
    List<Issue> check(Path path, BuildFileAST ast, FileFacade fileFacade);
  }
}
