// 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.apple;

import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;
import com.google.devtools.build.lib.analysis.ConfiguredTarget;
import com.google.devtools.build.lib.analysis.RedirectChaser;
import com.google.devtools.build.lib.analysis.RuleConfiguredTargetBuilder;
import com.google.devtools.build.lib.analysis.RuleContext;
import com.google.devtools.build.lib.analysis.RunfilesProvider;
import com.google.devtools.build.lib.analysis.config.ConfigurationEnvironment;
import com.google.devtools.build.lib.analysis.config.InvalidConfigurationException;
import com.google.devtools.build.lib.cmdline.Label;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.packages.BuildType;
import com.google.devtools.build.lib.packages.NoSuchPackageException;
import com.google.devtools.build.lib.packages.NoSuchTargetException;
import com.google.devtools.build.lib.packages.NonconfigurableAttributeMapper;
import com.google.devtools.build.lib.packages.Rule;
import com.google.devtools.build.lib.packages.Target;
import com.google.devtools.build.lib.rules.RuleConfiguredTargetFactory;
import com.google.devtools.build.lib.syntax.Type;

import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;

/**
 * Implementation for the {@code xcode_config} rule.
 */
public class XcodeConfig implements RuleConfiguredTargetFactory {

  @Override
  public ConfiguredTarget create(RuleContext ruleContext) throws InterruptedException {
    return new RuleConfiguredTargetBuilder(ruleContext)
        .addProvider(RunfilesProvider.class, RunfilesProvider.EMPTY)
        .build();
  }
  
  /**
   * Uses the {@link AppleCommandLineOptions#xcodeVersion} and
   * {@link AppleCommandLineOptions#xcodeVersionConfig} command line options to determine and
   * return the effective xcode version and its properties.
   *
   * @param env the current configuration environment
   * @param xcodeConfigLabel the label for the xcode_config target to parse
   * @param xcodeVersionOverrideFlag the value of the command line flag to override the default
   *     xcode version, absent if unspecified
   * @param errorDescription a description of the origin of {@code #xcodeConfigLabel} for messaging
   *     parse errors
   * @throws InvalidConfigurationException if the options given (or configuration targets) were
   *     malformed and thus the xcode version could not be determined
   */
  public static XcodeVersionProperties resolveXcodeVersion(ConfigurationEnvironment env,
      Label xcodeConfigLabel, Optional<DottedVersion> xcodeVersionOverrideFlag,
      String errorDescription) throws InvalidConfigurationException {
    Rule xcodeConfigRule =
        getRuleForLabel(xcodeConfigLabel, "xcode_config", env, errorDescription);

    XcodeVersionRuleData xcodeVersion =
        resolveExplicitlyDefinedVersion(env, xcodeConfigRule, xcodeVersionOverrideFlag);

    if (xcodeVersion != null) {
      return xcodeVersion.getXcodeVersionProperties();
    } else if (xcodeVersionOverrideFlag.isPresent()) {
      return new XcodeVersionProperties(xcodeVersionOverrideFlag.get());
    } else {
      return XcodeVersionProperties.unknownXcodeVersionProperties();
    }
  }

  /**
   * Returns the {@link XcodeVersionRuleData} associated with the {@code xcode_version} target
   * explicitly defined in the {@code --xcode_version_config} build flag and selected by the
   * {@code --xcode_version} flag. If {@code --xcode_version} is unspecified, then this
   * will return the default rule data as specified in the {@code --xcode_version_config} target.
   * Returns null if either the {@code --xcode_version} did not match any {@code xcode_version}
   * target, or if {@code --xcode_version} is unspecified and {@code --xcode_version_config}
   * specified no default target.
   */
  @Nullable private static XcodeVersionRuleData resolveExplicitlyDefinedVersion(
      ConfigurationEnvironment env, Rule xcodeConfigTarget,
      Optional<DottedVersion> versionOverrideFlag) throws InvalidConfigurationException {
    if (versionOverrideFlag.isPresent()) {
      // The version override flag is not necessarily an actual version - it may be a version
      // alias.
      XcodeVersionRuleData explicitVersion =
          aliasesToVersionMap(env, xcodeConfigTarget).get(versionOverrideFlag.get().toString());
      if (explicitVersion != null) {
        return explicitVersion;
      }
    } else { // No override specified. Use default.
      XcodeVersionRuleData defaultVersion = getDefaultVersion(env, xcodeConfigTarget);
      
      if (defaultVersion != null) {
        return defaultVersion;
      }
    }
    
    boolean requireDefinedVersions = NonconfigurableAttributeMapper.of(xcodeConfigTarget)
        .get(XcodeConfigRule.REQUIRE_DEFINED_VERSIONS_ATTR_NAME, Type.BOOLEAN);
    if (requireDefinedVersions) {
      throw new InvalidConfigurationException(
          "xcode version config required an explicitly defined version, but none was available");
    }

    return null;
  }

  /**
   * Returns the default xcode version to use, if no {@code --xcode_version} command line flag
   * was specified.
   */
  @Nullable private static XcodeVersionRuleData getDefaultVersion(ConfigurationEnvironment env,
      Rule xcodeConfigTarget) throws InvalidConfigurationException {
    Label defaultVersionLabel = NonconfigurableAttributeMapper.of(xcodeConfigTarget)
        .get(XcodeConfigRule.DEFAULT_ATTR_NAME, BuildType.LABEL);
    if (defaultVersionLabel != null) {
      Rule defaultVersionRule = getRuleForLabel(
          defaultVersionLabel, "xcode_version", env, "default xcode version");
      return new XcodeVersionRuleData(defaultVersionLabel, defaultVersionRule);
    } else {
      return null;
    }
  }

  private static Map<String, XcodeVersionRuleData> aliasesToVersionMap(ConfigurationEnvironment env,
      Rule xcodeConfigTarget) throws InvalidConfigurationException {
    List<Label> xcodeVersionLabels = NonconfigurableAttributeMapper.of(xcodeConfigTarget)
        .get(XcodeConfigRule.VERSIONS_ATTR_NAME, BuildType.LABEL_LIST);
    ImmutableList.Builder<XcodeVersionRuleData> xcodeVersionRuleListBuilder =
        ImmutableList.builder();
    for (Label label : xcodeVersionLabels) {
      Rule xcodeVersionRule = getRuleForLabel(label, "xcode_version", env, "xcode_version");
      xcodeVersionRuleListBuilder.add(new XcodeVersionRuleData(label, xcodeVersionRule));
    }
    ImmutableList<XcodeVersionRuleData> xcodeVersionRules = xcodeVersionRuleListBuilder.build();

    Map<String, XcodeVersionRuleData> aliasesToXcodeRules = Maps.newLinkedHashMap();
    for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) {
      for (String alias : xcodeVersionRule.getAliases()) {
        if (aliasesToXcodeRules.put(alias, xcodeVersionRule) != null) {
          configErrorDuplicateAlias(alias, xcodeVersionRules);
        }
      }
      if (aliasesToXcodeRules.put(
          xcodeVersionRule.getVersion().toString(), xcodeVersionRule) != null) {
        configErrorDuplicateAlias(xcodeVersionRule.getVersion().toString(), xcodeVersionRules);
      }
    }
    return aliasesToXcodeRules;
  }
  
  /**
   * Convenience method for throwing an {@link InvalidConfigurationException} due to presence
   * of duplicate aliases in an {@code xcode_config} target definition. 
   */
  private static void configErrorDuplicateAlias(String alias,
      List<XcodeVersionRuleData> xcodeVersionRules) throws InvalidConfigurationException {

    ImmutableList.Builder<Label> labelsContainingAlias = ImmutableList.builder();
    for (XcodeVersionRuleData xcodeVersionRule : xcodeVersionRules) {
      if (xcodeVersionRule.getAliases().contains(alias)
          || xcodeVersionRule.getVersion().toString().equals(alias)) {
        labelsContainingAlias.add(xcodeVersionRule.getLabel());
      }
    }

    throw new InvalidConfigurationException(
        String.format("'%s' is registered to multiple labels (%s) in a single xcode_config rule",
            alias, Joiner.on(", ").join(labelsContainingAlias.build())));
  }

  /**
   * If the given label (following redirects) is a target for a rule of type {@code type},
   * then returns the {@link Rule} representing that target. Otherwise, throws a
   * {@link InvalidConfigurationException}.
   */
  private static Rule getRuleForLabel(Label label, String type, ConfigurationEnvironment env,
      String description) throws InvalidConfigurationException {
    label = RedirectChaser.followRedirects(env, label, description);

    if (label == null) {
      throw new InvalidConfigurationException(String.format(
          "Expected value of %s (%s) to resolve to a target of type %s",
          description, label, type));
    }

    try {
      Target target = env.getTarget(label);
      
      if (target instanceof Rule && ((Rule) target).getRuleClass().equals(type)) {
        return (Rule) target;
      } else {
        throw new InvalidConfigurationException(String.format(
            "Expected value of %s (%s) to resolve to a target of type %s",
            description, label, type));
      }
    } catch (NoSuchPackageException | NoSuchTargetException exception) {
      env.getEventHandler().handle(Event.error(exception.getMessage()));
      throw new InvalidConfigurationException(exception);
    }
  }
}
