// Copyright 2015 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.lib.rules.objc;

import static com.google.common.base.CaseFormat.LOWER_UNDERSCORE;
import static com.google.common.base.CaseFormat.UPPER_CAMEL;
import static com.google.devtools.build.lib.packages.BuildType.LABEL_LIST;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.configuredtargets.RuleConfiguredTarget.Mode;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
import com.google.devtools.build.lib.collect.nestedset.NestedSetBuilder;
import com.google.devtools.build.lib.packages.RuleClass.ConfiguredTargetFactory.RuleErrorException;
import com.google.devtools.build.lib.rules.proto.ProtoSourceFileBlacklist;
import com.google.devtools.build.lib.rules.proto.ProtoSourcesProvider;
import com.google.devtools.build.lib.skyframe.ConfiguredTargetAndData;
import java.util.ArrayList;

/** Common rule attributes used by an objc_proto_library. */
final class ProtoAttributes {

  /**
   * List of file name segments that should be upper cased when being generated. More information
   * available in the generateProtobufFilename() method.
   */
  private static final ImmutableSet<String> UPPERCASE_SEGMENTS =
      ImmutableSet.of("url", "http", "https");

  @VisibleForTesting
  static final String PORTABLE_PROTO_FILTERS_EMPTY_ERROR =
      "The portable_proto_filters attribute can't be empty";

  @VisibleForTesting
  static final String NO_PROTOS_ERROR =
      "no protos to compile - a non-empty deps attribute is required";

  private final RuleContext ruleContext;

  /**
   * Creates a new ProtoAttributes object that wraps over objc_proto_library's attributes.
   *
   * @param ruleContext context of the objc_proto_library to wrap
   */
  ProtoAttributes(RuleContext ruleContext) {
    this.ruleContext = ruleContext;
  }

  /**
   * Validates the proto attributes for this target.
   *
   * <ul>
   * <li>Validates that there are protos specified to be compiled.
   * <li>Validates that, when enabling the open source protobuf library, the options for the PB2 are
   *     not specified also.
   * <li>Validates that, when enabling the open source protobuf library, the rule specifies at least
   *     one portable proto filter file.
   * </ul>
   */
  public void validate() throws RuleErrorException {
    if (getProtoFiles().isEmpty() && !hasObjcProtoLibraryDependencies()) {
      ruleContext.throwWithAttributeError("deps", NO_PROTOS_ERROR);
    }
    if (hasPortableProtoFilters() && getPortableProtoFilters().isEmpty()) {
      ruleContext.throwWithAttributeError(
          ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, PORTABLE_PROTO_FILTERS_EMPTY_ERROR);
    }
  }

  /**
   * Returns whether the target is an objc_proto_library. It does so by making sure that the
   * portable_proto_filters attribute exists in this target's attributes (even if it's empty).
   */
  boolean isObjcProtoLibrary() {
    return ruleContext.attributes().has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR);
  }

  private boolean isObjcProtoLibrary(ConfiguredTargetAndData dependency) {
    try {
      String targetName = dependency.getTarget().getTargetKind();
      return targetName.equals("objc_proto_library rule");
    } catch (Exception e) {
      return false;
    }
  }

  /** Returns whether to use the protobuf library instead of the PB2 library. */
  boolean hasPortableProtoFilters() {
    return ruleContext
        .attributes()
        .isAttributeValueExplicitlySpecified(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR);
  }

  /** Returns the list of portable proto filters. */
  ImmutableList<Artifact> getPortableProtoFilters() {
    if (ruleContext
        .attributes()
        .has(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, LABEL_LIST)) {
      return ruleContext
          .getPrerequisiteArtifacts(ObjcProtoLibraryRule.PORTABLE_PROTO_FILTERS_ATTR, Mode.HOST)
          .list();
    }
    return ImmutableList.of();
  }

  /** Returns the list of well known type protos. */
  ImmutableList<Artifact> getWellKnownTypeProtos() {
    return ruleContext
        .getPrerequisiteArtifacts(ObjcRuleClasses.PROTOBUF_WELL_KNOWN_TYPES, Mode.HOST)
        .list();
  }

  /** Returns the list of proto files to compile. */
  NestedSet<Artifact> getProtoFiles() {
    return NestedSetBuilder.<Artifact>stableOrder()
        .addTransitive(getProtoDepsSources())
        .build();
  }

  /** Returns the proto compiler to be used. */
  Artifact getProtoCompiler() {
    return ruleContext.getPrerequisiteArtifact(ObjcRuleClasses.PROTO_COMPILER_ATTR, Mode.HOST);
  }

  /** Returns the list of files needed by the proto compiler. */
  Iterable<Artifact> getProtoCompilerSupport() {
    return ruleContext
        .getPrerequisiteArtifacts(ObjcRuleClasses.PROTO_COMPILER_SUPPORT_ATTR, Mode.HOST)
        .list();
  }

  /**
   * Filters the well known protos from the given list of proto files. This should be used to
   * prevent the well known protos from being generated as they are already generated in the runtime
   * library.
   */
  Iterable<Artifact> filterWellKnownProtos(Iterable<Artifact> protoFiles) {
    ProtoSourceFileBlacklist wellKnownProtoBlacklist =
        new ProtoSourceFileBlacklist(ruleContext, getWellKnownTypeProtos());
    return wellKnownProtoBlacklist.filter(protoFiles);
  }

  /** Returns whether the given proto is a well known proto or not. */
  boolean isProtoWellKnown(Artifact protoFile) {
    ProtoSourceFileBlacklist wellKnownProtoBlacklist =
        new ProtoSourceFileBlacklist(ruleContext, getWellKnownTypeProtos());
    return wellKnownProtoBlacklist.isBlacklisted(protoFile);
  }

  /**
   * Processes the case of the proto file name in the same fashion as the objective_c generator's
   * UnderscoresToCamelCase function. This converts snake case to camel case by splitting words
   * by non alphabetic characters. This also treats the URL, HTTP and HTTPS as special words that
   * need to be completely uppercase.
   *
   * Examples:
   *   - j2objc_descriptor -> J2ObjcDescriptor (notice that O is uppercase after the 2)
   *   - my_http_url_array -> MyHTTPURLArray
   *   - proto-descriptor  -> ProtoDescriptor
   *
   * Original code reference:
   * <p>https://github.com/google/protobuf/blob/master/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
   */
  String getGeneratedProtoFilename(String protoFilename, boolean upcaseReservedWords) {
    boolean lastCharWasDigit = false;
    boolean lastCharWasUpper = false;
    boolean lastCharWasLower = false;

    StringBuilder currentSegment = new StringBuilder();

    ArrayList<String> segments = new ArrayList<>();

    for (int i = 0; i < protoFilename.length(); i++) {
      char currentChar = protoFilename.charAt(i);
      if (CharMatcher.javaDigit().matches(currentChar)) {
        if (!lastCharWasDigit) {
          segments.add(currentSegment.toString());
          currentSegment = new StringBuilder();
        }
        currentSegment.append(currentChar);
        lastCharWasDigit = true;
        lastCharWasUpper = false;
        lastCharWasLower = false;
      } else if (CharMatcher.javaLowerCase().matches(currentChar)) {
        if (!lastCharWasLower && !lastCharWasUpper) {
          segments.add(currentSegment.toString());
          currentSegment = new StringBuilder();
        }
        currentSegment.append(currentChar);
        lastCharWasDigit = false;
        lastCharWasUpper = false;
        lastCharWasLower = true;
      } else if (CharMatcher.javaUpperCase().matches(currentChar)) {
        if (!lastCharWasUpper) {
          segments.add(currentSegment.toString());
          currentSegment = new StringBuilder();
        }
        currentSegment.append(Character.toLowerCase(currentChar));
        lastCharWasDigit = false;
        lastCharWasUpper = true;
        lastCharWasLower = false;
      } else {
        lastCharWasDigit = false;
        lastCharWasUpper = false;
        lastCharWasLower = false;
      }
    }

    segments.add(currentSegment.toString());

    StringBuilder casedSegments = new StringBuilder();
    for (String segment : segments) {
      if (upcaseReservedWords && UPPERCASE_SEGMENTS.contains(segment)) {
        casedSegments.append(segment.toUpperCase());
      } else {
        casedSegments.append(LOWER_UNDERSCORE.to(UPPER_CAMEL, segment));
      }
    }
    return casedSegments.toString();
  }

  /** Returns the sets of proto files that were added using proto_library dependencies. */
  private NestedSet<Artifact> getProtoDepsSources() {
    NestedSetBuilder<Artifact> artifacts = NestedSetBuilder.stableOrder();
    Iterable<ProtoSourcesProvider> providers =
        ruleContext.getPrerequisites("deps", Mode.TARGET, ProtoSourcesProvider.class);
    for (ProtoSourcesProvider provider : providers) {
      artifacts.addTransitive(provider.getTransitiveProtoSources());
    }
    return artifacts.build();
  }

  private boolean hasObjcProtoLibraryDependencies() {
    for (ConfiguredTargetAndData dep :
        ruleContext.getPrerequisiteConfiguredTargetAndTargets("deps", Mode.TARGET)) {
      if (isObjcProtoLibrary(dep)) {
        return true;
      }
    }
    return false;
  }
}
