/*
 * Copyright 2000-2011 JetBrains s.r.o.
 *
 * 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 git4idea.commands;

import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.util.Key;
import gnu.trove.TObjectDoubleHashMap;
import gnu.trove.TObjectDoubleProcedure;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Captures standard remote operation notifications: "counting objects", "compressing objects", "receiving objects", "resolving deltas" and returns the fraction based on the stage of the command execution.
 * Some operations or some progress indications may be skipped - this will be handled properly.
 * @author Kirill Likhodedov
 */
public class GitStandardProgressAnalyzer implements GitProgressAnalyzer {

  // progress of each operation is stored here. this is an overhead since operations go one by one,
  // but it looks simpler than storing current operation, checking that ther was no skipped, etc.
  private TObjectDoubleHashMap<Operation> myOperationsProgress = new TObjectDoubleHashMap<Operation>(4);

  public static GitLineHandlerListener createListener(final ProgressIndicator indicator) {
    final GitStandardProgressAnalyzer progressAnalyzer = new GitStandardProgressAnalyzer();
    return new GitLineHandlerAdapter() {
      @Override
      public void onLineAvailable(String line, Key outputType) {
        final double fraction = progressAnalyzer.analyzeProgress(line);
        if (fraction >= 0) {
          indicator.setFraction(fraction);
        }
      }
    };
  }

  /**
   * A long git command usually consists of the operations in this enum.
   * A pattern is used to match the operation from the git output. fraction is used to indicate which part of the total git command
   * this operation takes (these numbers are not strict, we can't predict how much it will take in reality):
   * counting objects - 5%
   * compressing objects - 10 %
   * receiving objects - 80 %
   * resolving deltas - 5 %
   */
  private enum Operation {
    COUNTING_OBJECTS(".*Counting objects: +(\\d+).*", 0.05) {
      @Override
      double getProgress(int outputNumber) { // no percentage is given. +20% on each thousand objects.
        if (outputNumber > 5000) {
          return 1;
        }
        return outputNumber / 5000.0;
      }
    },
    COMPRESSING_OBJECTS(".*Compressing objects: +(\\d{1,3})%.*", 0.1),
    RECEIVING_OR_WRITING_OBJECTS(".*(?:Receiving|Writing) objects: +(\\d{1,3})%.*", 0.8), // receiving on fetch, writing on push
    RESOLVING_DELTAS(".*Resolving deltas: +(\\d{1,3})%.*", 0.05);

    private Pattern myPattern;
    private double myFractionInTotal;

    Operation(String pattern, double fractionInTotal) {
      myPattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
      myFractionInTotal = fractionInTotal;
    }

    /**
     * Returns the progress of the operation - the completed fraction (between 0 and 1.0) - basing on the integer given by the git
     * command output. This output number usually is a percent, but it may vary (see implementations of the method).
     */
    double getProgress(int outputNumber) {
      return outputNumber / 100.0;
    }
  }

  @Override
  public double analyzeProgress(String output) {
    for (Operation operation : Operation.values()) {
      final Matcher matcher = operation.myPattern.matcher(output);
      if (matcher.matches()) {
        try {
          double operationProgress = operation.getProgress(Integer.parseInt(matcher.group(1))); // progress of this operation
          myOperationsProgress.put(operation, operationProgress);
        } catch (NumberFormatException e) {
          return -1;
        }
        return updateTotalProgress(operation);
      }
    }
    return -1;
  }

  private double updateTotalProgress(Operation currentOperation) {
    // marking all operations before this one as completed
    for (Operation op : Operation.values()) {
      if (currentOperation.compareTo(op) > 0) {
        myOperationsProgress.put(op, 1.0);
      }
    }
    // counting progress
    final double[] totalProgress = new double[1];
    myOperationsProgress.forEachEntry(new TObjectDoubleProcedure<Operation>() {
      @Override
      public boolean execute(Operation operation, double progress) {
        totalProgress[0] += operation.myFractionInTotal * progress;
        return true;
      }
    });
    return totalProgress[0];
  }

}
