/*
 * 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.idea.blaze.cpp.includes;

import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiComment;
import com.jetbrains.cidr.lang.editor.OCCommenter;
import com.jetbrains.cidr.lang.psi.OCFile;
import com.jetbrains.cidr.lang.psi.OCIncludeDirective;
import com.jetbrains.cidr.lang.psi.visitors.OCRecursiveVisitor;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Parses IWYU pragmas specified in a given file.
 *
 * <p>See:
 * https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md
 */
final class IwyuPragmas {
  private static final String IWYU_PREFIX = "IWYU pragma:";

  public final OCFile file;
  public final Optional<PrivatePragma> privatePragma;
  public final ImmutableSet<KeepPragma> keeps;
  public final ImmutableSet<ExportPragma> exports;
  public final Optional<IncludePath> associatedHeader;

  private IwyuPragmas(
      OCFile file,
      Optional<PrivatePragma> privatePragma,
      ImmutableSet<KeepPragma> keeps,
      ImmutableSet<ExportPragma> exports,
      Optional<IncludePath> associatedHeader) {
    this.file = file;
    this.privatePragma = privatePragma;
    this.keeps = keeps;
    this.exports = exports;
    this.associatedHeader = associatedHeader;
  }

  public static IwyuPragmas parse(OCFile file) {
    BuildingVisitor builder = new BuildingVisitor(file);
    file.accept(builder);
    return builder.build();
  }

  /** Parse pragmas that are trailing comments */
  interface TrailingPragmaParser {
    /**
     * Checks if the pragmaContent is parsed by this parser, and updates the builder state if it is
     * actually parsed.
     *
     * @param builder builder to update on success
     * @param directive include directive with a trailing pragma comment
     * @param pragmaContent content from the pragma comment to parse
     * @return true if handled by this parser
     */
    boolean tryParse(BuildingVisitor builder, OCIncludeDirective directive, String pragmaContent);
  }

  /** Parse pragmas are standalone comments */
  interface StandalonePragmaParser {
    /**
     * Checks if the pragmaContent is parsed by this parser, and updates the builder state if it is
     * actually parsed.
     *
     * @param builder builder to update on success
     * @param pragmaContent content from the pragma comment to parse
     * @return true if handled by this parser
     */
    boolean tryParse(BuildingVisitor builder, String pragmaContent);
  }

  /** Represents a "keep" pragma */
  @AutoValue
  public abstract static class KeepPragma {
    /* TODO: keep pragmas can also be attached to a forward include. We don't yet handle that */
    private static final TrailingPragmaParser PARSER = new Parser();

    abstract IncludePath includePath();

    static KeepPragma create(IncludePath includePath) {
      return new AutoValue_IwyuPragmas_KeepPragma(includePath);
    }

    private static class Parser implements TrailingPragmaParser {
      private static final Pattern KEEP_PATTERN = Pattern.compile("^\\s*keep\\s*$");

      @Override
      public boolean tryParse(
          BuildingVisitor builder, OCIncludeDirective directive, String pragmaContent) {
        Matcher matcher = KEEP_PATTERN.matcher(pragmaContent);
        if (!matcher.find()) {
          return false;
        }
        builder.keeps.add(
            KeepPragma.create(
                IncludePath.create(directive.getReferenceText(), directive.getDelimiters())));
        return true;
      }
    }
  }

  /** Represents an "export" pragma */
  @AutoValue
  public abstract static class ExportPragma {
    private static final TrailingPragmaParser TRAIL_PARSER = new TrailParser();
    private static final StandalonePragmaParser RANGE_PARSER = new RangeParser();

    abstract IncludePath includePath();

    static ExportPragma create(IncludePath includePath) {
      return new AutoValue_IwyuPragmas_ExportPragma(includePath);
    }

    private static class TrailParser implements TrailingPragmaParser {

      private static final Pattern EXPORT_PATTERN = Pattern.compile("^\\s*export\\s*$");

      @Override
      public boolean tryParse(
          BuildingVisitor builder, OCIncludeDirective directive, String pragmaContent) {
        Matcher matcher = EXPORT_PATTERN.matcher(pragmaContent);
        if (!matcher.find()) {
          return false;
        }
        builder.exports.add(
            ExportPragma.create(
                IncludePath.create(directive.getReferenceText(), directive.getDelimiters())));
        return true;
      }
    }

    private static class RangeParser implements StandalonePragmaParser {

      private static final Pattern BEGIN_PATTERN = Pattern.compile("^\\s*begin_exports\\s*$");
      private static final Pattern END_PATTERN = Pattern.compile("^\\s*end_exports\\s*$");

      @Override
      public boolean tryParse(BuildingVisitor builder, String pragmaContent) {
        Matcher matcher = BEGIN_PATTERN.matcher(pragmaContent);
        if (matcher.matches()) {
          builder.includesInRange.clear();
          builder.collectRange = true;
          return true;
        }
        matcher = END_PATTERN.matcher(pragmaContent);
        if (matcher.matches()) {
          builder.collectRange = false;
          for (OCIncludeDirective directive : builder.includesInRange) {
            builder.exports.add(
                ExportPragma.create(
                    IncludePath.create(directive.getReferenceText(), directive.getDelimiters())));
          }
          builder.includesInRange.clear();
          return true;
        }
        return false;
      }
    }
  }

  /** Represents the "private" pragma */
  public static class PrivatePragma {
    private static final StandalonePragmaParser PARSER = new Parser();

    public final Optional<IncludePath> includeOther;

    PrivatePragma(IncludePath includeOther) {
      this.includeOther = Optional.of(includeOther);
    }

    PrivatePragma() {
      this.includeOther = Optional.empty();
    }

    private static class Parser implements StandalonePragmaParser {
      private static final Pattern PRIVATE_PATTERN =
          Pattern.compile("^\\s*private\\s*(,\\s*include\\s*(?<includename>.*)\\s*)?$");

      @Override
      public boolean tryParse(BuildingVisitor builder, String pragmaContent) {
        Matcher matcher = PRIVATE_PATTERN.matcher(pragmaContent);
        if (!matcher.find()) {
          return false;
        }
        String alternateInclude = matcher.group("includename");
        if (alternateInclude != null) {
          builder.privatePragma =
              Optional.of(new PrivatePragma(IncludePath.create(alternateInclude)));
        } else {
          builder.privatePragma = Optional.of(new PrivatePragma());
        }
        return true;
      }
    }
  }

  /** Represents the "associated" pragma */
  public static class AssociatedPragma {
    private static final TrailingPragmaParser PARSER = new Parser();

    private static class Parser implements TrailingPragmaParser {
      private static final Pattern ASSOCIATED_PATTERN = Pattern.compile("^\\s*associated\\s*$");

      @Override
      public boolean tryParse(
          BuildingVisitor builder, OCIncludeDirective directive, String pragmaContent) {
        Matcher matcher = ASSOCIATED_PATTERN.matcher(pragmaContent);
        if (!matcher.find()) {
          return false;
        }
        builder.associatedHeader =
            Optional.of(
                IncludePath.create(directive.getReferenceText(), directive.getDelimiters()));
        return true;
      }
    }
  }

  private static final ImmutableList<TrailingPragmaParser> TRAILING_PARSERS =
      ImmutableList.of(KeepPragma.PARSER, ExportPragma.TRAIL_PARSER, AssociatedPragma.PARSER);
  private static final ImmutableList<StandalonePragmaParser> STANDALONE_PARSERS =
      ImmutableList.of(ExportPragma.RANGE_PARSER, PrivatePragma.PARSER);

  private static class BuildingVisitor extends OCRecursiveVisitor {

    final OCFile file;
    final OCCommenter commenter;

    Optional<PrivatePragma> privatePragma = Optional.empty();
    ImmutableSet.Builder<KeepPragma> keeps = ImmutableSet.builder();
    ImmutableSet.Builder<ExportPragma> exports = ImmutableSet.builder();
    Optional<IncludePath> associatedHeader = Optional.empty();

    List<OCIncludeDirective> includesInRange = new ArrayList<>();
    boolean collectRange;

    BuildingVisitor(OCFile file) {
      this.file = file;
      this.commenter = new OCCommenter();
    }

    IwyuPragmas build() {
      return new IwyuPragmas(file, privatePragma, keeps.build(), exports.build(), associatedHeader);
    }

    @Override
    public void visitImportDirective(OCIncludeDirective directive) {
      if (collectRange) {
        includesInRange.add(directive);
      }
      visitTrailingComments(directive);
      super.visitImportDirective(directive);
    }

    @Override
    public void visitComment(PsiComment comment) {
      String text = trimCommentContent(comment.getText());
      if (text.startsWith(IWYU_PREFIX)) {
        String pragmaContent = StringUtil.trimStart(text, IWYU_PREFIX);
        for (StandalonePragmaParser parser : STANDALONE_PARSERS) {
          if (parser.tryParse(this, pragmaContent)) {
            break;
          }
        }
      }
      super.visitComment(comment);
    }

    // In older CIDR implementations, trailing comments are not separate PsiComment nodes. They
    // are simply part of the "directive content" PsiElement (which also has #include path).
    // Thus, we have to handle it at the OCIncludeDirective level instead of waiting for
    // visitComment() to run. In newer CIDR implementations, trailing comments are a separate
    // PsiComment node, but they are still a child of the OCIncludeDirective, so pragma should be
    // found in the directive's getText().
    private void visitTrailingComments(OCIncludeDirective directive) {
      String fullText = directive.getText();
      String pathText = directive.getReferenceText();
      if (pathText.isEmpty()) {
        return;
      }
      String afterPath = fullText.substring(fullText.indexOf(pathText) + pathText.length());
      OCIncludeDirective.Delimiters delimiters = directive.getDelimiters();
      int delimIndex = afterPath.indexOf(delimiters.getAfterText());
      if (delimIndex == -1) {
        return;
      }
      afterPath = afterPath.substring(delimIndex + delimiters.getAfterText().length()).trim();
      String trimmed = trimCommentContent(afterPath);
      if (trimmed.startsWith(IWYU_PREFIX)) {
        String pragmaContent = StringUtil.trimStart(trimmed, IWYU_PREFIX);
        for (TrailingPragmaParser parser : TRAILING_PARSERS) {
          if (parser.tryParse(this, directive, pragmaContent)) {
            break;
          }
        }
      }
    }

    private String trimCommentContent(String text) {
      if (text.startsWith(commenter.getLineCommentPrefix())) {
        return StringUtil.trimStart(text, commenter.getLineCommentPrefix()).trim();
      } else if (text.startsWith(commenter.getBlockCommentPrefix())) {
        return StringUtil.trimEnd(
                StringUtil.trimStart(text, commenter.getBlockCommentPrefix()),
                commenter.getBlockCommentSuffix())
            .trim();
      }
      return text.trim();
    }
  }
}
