// Copyright (C) 2017 The Android Open Source Project
//
// 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.googlesource.gerrit.plugins.findowners;

import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Keep owned files and count number of files at control level 1, 2, 3, etc.
 *
 * <p>A source file can be owned by multiple OWNERS file in its directory or parent directories. The
 * owners listed in the lowest OWNERS file has level 1 control of that source file. The 2nd lowest
 * OWNERS file has level 2 control, etc.
 *
 * <p>An owner can own multiple source files at different control level.
 *
 * <p>Each owner has an OwnerWeights object to keep (0) the set of owned files, (1) number of owned
 * files with level 1 control, (2) number of owned files with level 2 control, (3) number of owned
 * files with level 3 or higher control,
 */
class OwnerWeights {
  static class WeightComparator implements Comparator<String> {
    private Map<String, OwnerWeights> map;

    WeightComparator(Map<String, OwnerWeights> weights) {
      map = weights;
    }

    @Override
    public int compare(String k1, String k2) {
      OwnerWeights w1 = map.get(k1);
      OwnerWeights w2 = map.get(k2);
      int n1 = w2.countL1 - w1.countL1;
      int n2 = w2.countL2 - w1.countL2;
      int n3 = w2.countL3 - w1.countL3;
      return n1 != 0 ? n1 : (n2 != 0 ? n2 : (n3 != 0 ? n3 : k1.compareTo(k2)));
    }
  }

  Set<String> files = new HashSet<>(); // paths of owned files
  int countL1; // number of files with control level 1
  int countL2; // number of files with control level 2
  int countL3; // number of files with control level 3 or more

  /** Return file counters as a compact string. */
  String encodeLevelCounts() {
    return "[" + countL1 + "+" + countL2 + "+" + countL3 + "]";
  }

  /** Return file counters as a list of integers. */
  List<Integer> getLevelCounts() {
    return ImmutableList.of(countL1, countL2, countL3);
  }

  OwnerWeights(String file, int level) {
    addFile(file, level);
  }

  OwnerWeights() {}

  void addFile(String path, int level) {
    // If a file is added multiple times,
    // it should be added with lowest level first.
    if (!files.contains(path)) {
      files.add(path);
      if (level <= 1) {
        countL1++;
      } else if (level <= 2) {
        countL2++;
      } else {
        countL3++;
      }
    }
  }

  /** Sort keys in weights map by control levels, and return keys. */
  static List<String> sortKeys(Map<String, OwnerWeights> weights) {
    List<String> keys = new ArrayList<>(weights.keySet());
    Collections.sort(keys, new WeightComparator(weights));
    return keys;
  }
}
