/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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 org.apache.servicecomb.faultinjection;

import static org.apache.servicecomb.faultinjection.FaultInjectionConst.CONSUMER_FAULTINJECTION;
import static org.apache.servicecomb.faultinjection.FaultInjectionConst.CONSUMER_FAULTINJECTION_GLOBAL;
import static org.apache.servicecomb.faultinjection.FaultInjectionConst.CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS;
import static org.apache.servicecomb.faultinjection.FaultInjectionConst.FAULT_INJECTION_DEFAULT_VALUE;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import com.google.common.annotations.VisibleForTesting;
import org.apache.servicecomb.core.Invocation;
import org.apache.servicecomb.foundation.common.concurrent.ConcurrentHashMapEx;

/**
 * Handles the count for all request based key[transport + microservice qualified name].
 */
public class FaultInjectionUtil {
  private FaultInjectionUtil() {
  }

  // key is transport+operQualifiedName
  private static final Map<String, AtomicLong> requestCount = new ConcurrentHashMapEx<>();

  // key is config paramter
  private static final Map<String, AtomicInteger> configCenterValue = new ConcurrentHashMapEx<>();

  /**
   * Returns total requests per provider for operational level.
   *
   * @param key
   *            transport+operational name
   * @return long total requests
   */
  public static AtomicLong getOperMetTotalReq(String key) {
    return requestCount.computeIfAbsent(key, p -> new AtomicLong(1));
  }

  /**
   * Returns the map of config parameter key and values.
   * @return value of config parameter map
   */
  public static Map<String, AtomicInteger> getConfigCenterMap() {
    return configCenterValue;
  }

  /**
   * Sets the value for given config parameter.
   * @param key
   * @param value
   */
  public static void setConfigCenterValue(String key, AtomicInteger value) {
    configCenterValue.put(key, value);
  }

  /**
   * Handles the reading fault injection configuration.
   *
   * @param invocation
   *            invocation of request
   * @param key
   *            configuration key
   * @return configuration value
   */
  public static int getFaultInjectionConfig(Invocation invocation, String key) {
    int value = 0;
    String config;

    // get the config base on priority. operationName-->schema-->service-->global
    String operationName = invocation.getOperationName();
    String schema = invocation.getSchemaId();
    String serviceName = invocation.getMicroserviceName();

    config = CONSUMER_FAULTINJECTION + serviceName + ".schemas." + schema + ".operations." + operationName + "."
        + CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS + invocation.getTransport().getName() + "." + key;

    value = getConfigValue(config);
    if ((value != FAULT_INJECTION_DEFAULT_VALUE)) {
      return value;
    }

    config = CONSUMER_FAULTINJECTION + serviceName + ".schemas." + schema + "."
        + CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS + invocation.getTransport().getName() + "." + key;

    value = getConfigValue(config);
    if ((value != FAULT_INJECTION_DEFAULT_VALUE)) {
      return value;
    }

    config = CONSUMER_FAULTINJECTION + serviceName + "." + CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS
        + invocation.getTransport().getName() + "." + key;
    value = getConfigValue(config);
    if ((value != FAULT_INJECTION_DEFAULT_VALUE)) {
      return value;
    }

    config = CONSUMER_FAULTINJECTION_GLOBAL + CONSUMER_FAULTINJECTION_POLICY_PROTOCOLS
        + invocation.getTransport().getName() + "." + key;

    value = getConfigValue(config);
    return value;
  }

  /**
   * Get the configuration value
   * @param config config parameter
   * @return int value
   */
  private static int getConfigValue(String config) {
    int value = 0;
    //first need to check in config center map which has high priority.
    Map<String, AtomicInteger> cfgMap = FaultInjectionUtil.getConfigCenterMap();

    if (cfgMap.containsKey(config)) {
      return cfgMap.get(config).get();
    }

    value = FaultInjectionConfig.getConfigVal(config, FAULT_INJECTION_DEFAULT_VALUE);
    return value;
  }

  /**
   * It will check the delay/abort condition based on request count and percentage
   * received.
   *
   * @param reqCount
   * @param percentage
   * @return true: delay/abort is needed. false: delay/abort is not needed.
   */
  public static boolean isFaultNeedToInject(long reqCount, int percentage) {
    /*
     * Example: delay/abort percentage configured is 10% and Get the count(suppose
     * if it is 10th request) from map and calculate resultNew(10th request) and
     * requestOld(9th request). Like this for every request it will calculate
     * current request count and previous count. if both not matched need to add
     * delay/abort otherwise no need to add.
     */

    // calculate the value with current request count.
    long resultNew = (reqCount * percentage) / 100;

    // calculate the value with previous count value.
    long resultOld = ((reqCount - 1) * percentage) / 100;

    // if both are not matching then delay/abort should be added.
    return (resultNew != resultOld);
  }

  @VisibleForTesting
  static Map<String, AtomicLong> getRequestCount() {
    return requestCount;
  }

  @VisibleForTesting
  static Map<String, AtomicInteger> getConfigCenterValue() {
    return configCenterValue;
  }
}
