// 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.lib.packages;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableTable;
import com.google.common.collect.Sets;
import com.google.common.collect.Table;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.cmdline.LabelSyntaxException;
import com.google.devtools.build.lib.concurrent.ThreadSafety.Immutable;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.events.EventHandler;
import com.google.devtools.build.lib.events.Location;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec;
import com.google.devtools.build.lib.skyframe.serialization.autocodec.AutoCodec.VisibleForSerialization;
import com.google.devtools.build.lib.skylarkbuildapi.LicenseApi;
import com.google.devtools.build.lib.skylarkinterface.SkylarkPrinter;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/** Support for license and distribution checking. */
@Immutable
@ThreadSafe
@AutoCodec
public final class License implements LicenseApi {
  private final ImmutableSet<LicenseType> licenseTypes;
  private final ImmutableSet<Label> exceptions;

  /**
   * The error that's thrown if a build file contains an invalid license string.
   */
  public static class LicenseParsingException extends Exception {
    public LicenseParsingException(String s) {
      super(s);
    }
  }

  /**
   * LicenseType is the basis of the License lattice - stricter licenses should
   * be declared before less-strict licenses in the enum.
   *
   * <p>Note that the order is important for the purposes of finding the least
   * restrictive license.
   */
  public enum LicenseType {
    BY_EXCEPTION_ONLY,
    RESTRICTED,
    RESTRICTED_IF_STATICALLY_LINKED,
    RECIPROCAL,
    NOTICE,
    PERMISSIVE,
    UNENCUMBERED,
    NONE
  }

  /**
   * Gets the least restrictive license type from the list of licenses declared
   * for a target. For the purposes of license checking, the license type set of
   * a declared license can be reduced to its least restrictive member.
   *
   * @param types a collection of license types
   * @return the least restrictive license type
   */
  @VisibleForTesting
  static LicenseType leastRestrictive(Collection<LicenseType> types) {
    return types.isEmpty() ? LicenseType.BY_EXCEPTION_ONLY : Collections.max(types);
  }

  /**
   * An instance of LicenseType.None with no exceptions, used for packages outside of third_party
   * which have no license clause in their BUILD files.
   */
  public static final License NO_LICENSE =
      new License(ImmutableSet.of(LicenseType.NONE), ImmutableSet.of());

  /**
   * A default instance of Distributions which is used for packages which
   * have no "distribs" declaration. If nothing is declared, we opt for the
   * most permissive kind of distribution, which is the internal-only distrib.
   */
  public static final Set<DistributionType> DEFAULT_DISTRIB =
      Collections.singleton(DistributionType.INTERNAL);

  /**
   * The types of distribution that are supported.
   */
  public enum DistributionType {
    INTERNAL,
    WEB,
    CLIENT,
    EMBEDDED
  }

  /**
   * Parses a set of strings declaring distribution types.
   *
   * @param distStrings strings containing distribution declarations from BUILD
   *        files
   * @return a new, unmodifiable set of DistributionTypes
   * @throws LicenseParsingException
   */
  public static Set<DistributionType> parseDistributions(Collection<String> distStrings)
      throws LicenseParsingException {
    if (distStrings.isEmpty()) {
      return Collections.unmodifiableSet(EnumSet.of(DistributionType.INTERNAL));
    } else {
      Set<DistributionType> result = EnumSet.noneOf(DistributionType.class);
      for (String distStr : distStrings) {
        try {
          DistributionType dist = DistributionType.valueOf(distStr.toUpperCase(Locale.ENGLISH));
          result.add(dist);
        } catch (IllegalArgumentException e) {
          throw new LicenseParsingException("Invalid distribution type '" + distStr + "'");
        }
      }
      return Collections.unmodifiableSet(result);
    }
  }

  private static final Object MARKER = new Object();

  /**
   * The license incompatibility set. This contains the set of
   * (Distribution,License) pairs that should generate errors.
   */
  private static Table<DistributionType, LicenseType, Object> LICENSE_INCOMPATIBILIES =
      createLicenseIncompatibilitySet();

  private static Table<DistributionType, LicenseType, Object> createLicenseIncompatibilitySet() {
    Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
    result.put(DistributionType.CLIENT, LicenseType.RESTRICTED, MARKER);
    result.put(DistributionType.EMBEDDED, LicenseType.RESTRICTED, MARKER);
    result.put(DistributionType.INTERNAL, LicenseType.BY_EXCEPTION_ONLY, MARKER);
    result.put(DistributionType.CLIENT, LicenseType.BY_EXCEPTION_ONLY, MARKER);
    result.put(DistributionType.WEB, LicenseType.BY_EXCEPTION_ONLY, MARKER);
    result.put(DistributionType.EMBEDDED, LicenseType.BY_EXCEPTION_ONLY, MARKER);
    return ImmutableTable.copyOf(result);
  }

  /**
   * The license warning set. This contains the set of
   * (Distribution,License) pairs that should generate warnings when the user
   * requests verbose license checking.
   */
  private static Table<DistributionType, LicenseType, Object> LICENSE_WARNINGS =
      createLicenseWarningsSet();

  private static Table<DistributionType, LicenseType, Object> createLicenseWarningsSet() {
    Table<DistributionType, LicenseType, Object> result = HashBasedTable.create();
    result.put(DistributionType.CLIENT, LicenseType.RECIPROCAL, MARKER);
    result.put(DistributionType.EMBEDDED, LicenseType.RECIPROCAL, MARKER);
    result.put(DistributionType.CLIENT, LicenseType.NOTICE, MARKER);
    result.put(DistributionType.EMBEDDED, LicenseType.NOTICE, MARKER);
    return ImmutableTable.copyOf(result);
  }

  @AutoCodec.Instantiator
  @VisibleForSerialization
  License(ImmutableSet<LicenseType> licenseTypes, ImmutableSet<Label> exceptions) {
    // Defensive copy is done in .of()
    this.licenseTypes = licenseTypes;
    this.exceptions = exceptions;
  }

  public static License of(Collection<LicenseType> licenses, Collection<Label> exceptions) {
    ImmutableSet<LicenseType> licenseSet = ImmutableSet.copyOf(licenses);
    ImmutableSet<Label> exceptionSet = ImmutableSet.copyOf(exceptions);

    if (exceptionSet.isEmpty() && licenseSet.equals(ImmutableSet.of(LicenseType.NONE))) {
      return License.NO_LICENSE;
    }

    return new License(licenseSet, exceptionSet);
  }
  /**
   * Computes a license which can be used to check if a package is compatible
   * with some kinds of distribution. The list of licenses is scanned for the
   * least restrictive, and the exceptions are added.
   *
   * @param licStrings the list of license strings declared for the package
   * @throws LicenseParsingException if there are any parsing problems
   */
  public static License parseLicense(List<String> licStrings) throws LicenseParsingException {
    /*
     * The semantics of comparison for licenses depends on a stable iteration
     * order for both license types and exceptions. For licenseTypes, it will be
     * the comparison order from the enumerated types; for exceptions, it will
     * be lexicographic order achieved using TreeSets.
     */
    Set<LicenseType> licenseTypes = EnumSet.noneOf(LicenseType.class);
    Set<Label> exceptions = Sets.newTreeSet();
    for (String str : licStrings) {
      if (str.startsWith("exception=")) {
        try {
          Label label =
              Label.parseAbsolute(str.substring("exception=".length()), ImmutableMap.of());
          exceptions.add(label);
        } catch (LabelSyntaxException e) {
          throw new LicenseParsingException(e.getMessage());
        }
      } else {
        try {
          licenseTypes.add(LicenseType.valueOf(str.toUpperCase(Locale.ENGLISH)));
        } catch (IllegalArgumentException e) {
          throw new LicenseParsingException("invalid license type: '" + str + "'");
        }
      }
    }

    return License.of(licenseTypes, exceptions);
  }

  /**
   * Checks if this license is compatible with distributing a particular target
   * in some set of distribution modes.
   *
   * @param dists the modes of distribution
   * @param target the target which is being checked, and which will be used for
   *        checking exceptions
   * @param licensedTarget the target which declared the license being checked.
   * @param eventHandler a reporter where any licensing issues discovered should be
   *        reported
   * @param staticallyLinked whether the target is statically linked under this command
   * @return true if the license is compatible with the distributions
   */
  public boolean checkCompatibility(Set<DistributionType> dists,
      Target target, Label licensedTarget, EventHandler eventHandler,
      boolean staticallyLinked) {
    Location location = (target instanceof Rule) ? ((Rule) target).getLocation() : null;

    LicenseType leastRestrictiveLicense;
    if (licenseTypes.contains(LicenseType.RESTRICTED_IF_STATICALLY_LINKED)) {
      Set<LicenseType> tempLicenses = EnumSet.copyOf(licenseTypes);
      tempLicenses.remove(LicenseType.RESTRICTED_IF_STATICALLY_LINKED);
      if (staticallyLinked) {
        tempLicenses.add(LicenseType.RESTRICTED);
      } else {
        tempLicenses.add(LicenseType.UNENCUMBERED);
      }
      leastRestrictiveLicense = leastRestrictive(tempLicenses);
    } else {
      leastRestrictiveLicense = leastRestrictive(licenseTypes);
    }
    for (DistributionType dt : dists) {
      if (LICENSE_INCOMPATIBILIES.contains(dt, leastRestrictiveLicense)) {
        if (!exceptions.contains(target.getLabel())) {
          eventHandler.handle(Event.error(location, "Build target '" + target.getLabel()
              + "' is not compatible with license '" + this + "' from target '"
                  + licensedTarget + "'"));
          return false;
        }
      } else if (LICENSE_WARNINGS.contains(dt, leastRestrictiveLicense)) {
        eventHandler.handle(
            Event.warn(location, "Build target '" + target
                + "' has a potential licensing issue "
                + "with a '" + this + "' license from target '" + licensedTarget + "'"));
      }
    }
    return true;
  }

  /**
   * @return an immutable set of {@link LicenseType}s contained in this {@code
   *         License}
   */
  public Set<LicenseType> getLicenseTypes() {
    return licenseTypes;
  }

  /**
   * @return an immutable set of {@link Label}s that describe exceptions to the
   *         {@code License}
   */
  public Set<Label> getExceptions() {
    return exceptions;
  }

  @SuppressWarnings("ReferenceEquality")
  public boolean isSpecified() {
    return this != License.NO_LICENSE;
  }

  /**
   * A simple toString implementation which generates a canonical form of the
   * license. (The order of license types is guaranteed to be canonical by
   * EnumSet, and the order of exceptions is guaranteed to be lexicographic
   * order by TreeSet.)
   */
  @Override
  public String toString() {
    if (exceptions.isEmpty()) {
      return licenseTypes.toString().toLowerCase();
    } else {
      return licenseTypes.toString().toLowerCase() + " with exceptions " + exceptions;
    }
  }

  /**
   * A simple equals implementation leveraging the support built into Set that
   * delegates to its contents.
   */
  @Override
  public boolean equals(Object o) {
    return o == this || (o instanceof License
        && ((License) o).licenseTypes.equals(this.licenseTypes)
        && ((License) o).exceptions.equals(this.exceptions));
  }

  /**
   * A simple hashCode implementation leveraging the support built into Set that
   * delegates to its contents.
   */
  @Override
  public int hashCode() {
    return licenseTypes.hashCode() * 43 + exceptions.hashCode();
  }

  @Override
  public void repr(SkylarkPrinter printer) {
    printer.append("<license object>");
  }
}
