/*
 * Copyright 2014-present Facebook, Inc.
 *
 * 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.facebook.buck.cli;

import com.facebook.buck.rules.Label;
import com.facebook.infer.annotation.SuppressFieldNotInitialized;
import com.google.common.base.Preconditions;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Maps;

import org.kohsuke.args4j.CmdLineException;
import org.kohsuke.args4j.CmdLineParser;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.OptionDef;
import org.kohsuke.args4j.spi.OptionHandler;
import org.kohsuke.args4j.spi.Parameters;
import org.kohsuke.args4j.spi.Setter;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Options for including and excluding rules by label.
 * <p>
 * If we were starting from scratch, we'd just have a single command line option: --labels !foo bar
 * <p>
 * However, we have to support the historical dual-option form: --exclude foo --include bar
 * <p>
 * Order is significant as the first matching include/exclude rule wins.  To support the legacy
 * --include and --exclude options and yet still respect order, we use a special option handler
 * {@link com.facebook.buck.cli.TestLabelOptions.LabelsOptionHandler} which keeps track of the
 * argument position of each label-rule in the respective maps populated by those options.
 */
class TestLabelOptions {

  public static final String LABEL_SEPERATOR = "+";

  @Option(
      name = "--exclude",
      usage = "Labels to ignore when running tests, --exclude L1 L2 ... LN.",
      handler = LabelsOptionHandler.class)
  @SuppressFieldNotInitialized
  private Map<Integer, LabelSelector> excludedLabelSets;

  @Option(
      name = "--labels",
      aliases = {"--include"},
      usage =
          "Labels to include (or exclude, when prefixed with '!') when running test rules.  " +
          "The first matching statement is used to decide whether to " +
          "include or exclude a test rule.",
      handler = LabelsOptionHandler.class)
  @SuppressFieldNotInitialized
  private Map<Integer, LabelSelector> includedLabelSets;

  @Option(
      name = "--always-exclude",
      aliases = {"--always_exclude"},
      usage =
          "If set, an exclude filter will win over a target on the command line, so tests " +
          "that were both specified to run on the command line and are excluded through either " +
          "the '--exclude' option or in the .buckconfig will not run.")
  private boolean alwaysExclude;

  private Supplier<ImmutableList<LabelSelector>> supplier =
      Suppliers.memoize(new Supplier<ImmutableList<LabelSelector>>() {
        @Override
        public ImmutableList<LabelSelector> get() {
          TreeMap<Integer, LabelSelector> all = Maps.newTreeMap();
          all.putAll(includedLabelSets);

          // Invert the sense of anything given to --exclude.
          // This means we could --exclude !includeMe  ...lolololol
          for (Integer ordinal : excludedLabelSets.keySet()) {
            LabelSelector original = Preconditions.checkNotNull(excludedLabelSets.get(ordinal));
            all.put(ordinal, original.invert());
          }

          return ImmutableList.copyOf(all.values());
        }
      });

  public boolean shouldExcludeWin() {
    return alwaysExclude;
  }

  public boolean isMatchedByLabelOptions(BuckConfig buckConfig, Set<Label> rawLabels) {
    ImmutableList<LabelSelector> labelSelectors = supplier.get();
    for (LabelSelector labelSelector : labelSelectors) {
      if (labelSelector.matches(rawLabels)) {
        return labelSelector.isInclusive();
      }
    }

    List<String> defaultRawExcludedLabelSelectors =
        buckConfig.getDefaultRawExcludedLabelSelectors();
    for (String raw : defaultRawExcludedLabelSelectors) {
      LabelSelector labelSelector = LabelSelector.fromString(raw).invert();
      if (labelSelector.matches(rawLabels)) {
        return labelSelector.isInclusive();
      }
    }

    boolean defaultResult = true;
    for (LabelSelector labelSelector : labelSelectors) {
      if (labelSelector.isInclusive()) {
        defaultResult = false;
      }
    }

    return defaultResult;
  }

  public static class LabelsOptionHandler extends OptionHandler<Map<Integer, LabelSelector>> {

    /**
     * Shared across all instances of this handler, to keep track of the order of label rules given
     * on the command line.
     */
    private static final AtomicInteger ordinal = new AtomicInteger();

    private final Map<Integer, LabelSelector> labels = Maps.newHashMap();

    public LabelsOptionHandler(
        CmdLineParser parser,
        OptionDef option,
        Setter<Map<Integer, LabelSelector>> setter) throws CmdLineException {
      super(parser, option, setter);
      setter.addValue(labels);
    }

    @Override
    public int parseArguments(Parameters parameters) throws CmdLineException {
      int index;
      for (index = 0; index < parameters.size(); index++) {
        String parameter = parameters.getParameter(index);
        if (parameter.charAt(0) == '-') {
          break;
        }
        labels.put(ordinal.getAndIncrement(), LabelSelector.fromString(parameter));
      }
      return index;
    }

    @Override
    public String getDefaultMetaVariable() {
      return "LIST<LABELS>";
    }
  }
}
