//
// Copyright 2020 Google LLC
//
// 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.privacy.differentialprivacy;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.Double.isFinite;

import com.google.privacy.differentialprivacy.proto.SummaryOuterClass.MechanismType;
import java.util.Objects;
import javax.annotation.Nullable;

/** Utilities which validate the correctness of DP parameters. */
public class DpPreconditions {

  private DpPreconditions() {}

  static void checkEpsilon(double epsilon) {
    double epsilonLowerBound = 1.0 / (1L << 50);
    checkArgument(
        Double.isFinite(epsilon) && epsilon >= epsilonLowerBound,
        "epsilon must be >= %s and < infinity. Provided value: %s",
        epsilonLowerBound,
        epsilon);
  }

  static void checkNoiseDelta(Double delta, Noise noise) {
    if (noise.getMechanismType() == MechanismType.LAPLACE
        || noise.getMechanismType() == MechanismType.DISCRETE_LAPLACE) {
      checkArgument(
          delta == null,
          "delta should not be set when (Discrete) Laplace noise is used. Provided value: %s",
          delta);
    } else if (noise.getMechanismType() == MechanismType.GAUSSIAN) {
      checkNotNull(delta);
      checkDelta(delta);
      // For unknown noise, delta may or may not be null, but if it is not null it should be between
      // 0 and 1.
    } else if (delta != null) {
      checkArgument(
          delta >= 0 && delta < 1, "delta must be >= 0 and < 1. Provided value: %s", delta);
    }
  }

  static void checkDelta(double delta) {
    checkArgument(delta > 0 && delta < 1, "delta must be > 0 and < 1. Provided value: %s", delta);
  }

  static void checkSensitivities(int l0Sensitivity, double lInfSensitivity) {
    checkL0Sensitivity(l0Sensitivity);
    checkArgument(
        Double.isFinite(lInfSensitivity) && lInfSensitivity > 0,
        "lInfSensitivity must be > 0 and finite. Provided value: %s",
        lInfSensitivity);
  }

  static void checkL0Sensitivity(int l0Sensitivity) {
    checkArgument(
        l0Sensitivity > 0, "l0Sensitivity must be > 0. Provided value: %s", l0Sensitivity);
  }

  static void checkL1Sensitivity(double l1Sensitivity) {
    checkArgument(
        Double.isFinite(l1Sensitivity) && l1Sensitivity > 0,
        "l1Sensitivity must be > 0 and finite. Provided value: %s",
        l1Sensitivity);
  }

  static void checkMaxPartitionsContributed(int maxPartitionsContributed) {
    // maxPartitionsContributed is the user-facing parameter, which is technically the same as
    // L0 sensitivity used by the noise internally.
    checkL0Sensitivity(maxPartitionsContributed);
  }

  static void checkMaxContributionsPerPartition(int maxContributionsPerPartition) {
    checkArgument(
        maxContributionsPerPartition > 0,
        "maxContributionsPerPartitions must be > 0. Provided value: %s",
        maxContributionsPerPartition);
  }

  static void checkBounds(double lower, double upper) {
    checkArgument(
        upper >= lower,
        "The upper bound should be greater than the lower bound. Provided values: "
            + "lower = %s upper = %s",
        lower,
        upper);
    checkArgument(
        isFinite(lower) && isFinite(upper),
        "Lower and upper bounds should be finite. Provided values: " + "lower = %s upper = %s",
        lower,
        upper);
  }

  static void checkBoundsNotEqual(double lower, double upper) {
    checkArgument(
        upper != lower,
        "Lower and upper bounds cannot be equal to each other. Provided values: "
            + "lower = %s upper = %s",
        lower,
        upper);
  }

  static void checkMergeDeltaAreEqual(@Nullable Double delta1, double delta2) {
    if (delta1 != null) {
      checkArgument(
          Double.compare(delta1, delta2) == 0,
          "Failed to merge: unequal values of delta. " + "delta1 = %s, delta2 = %s",
          delta1,
          delta2);
    } else {
      checkArgument(
          Double.compare(delta2, 0.0) == 0,
          "Failed to merge: unequal values of delta. " + "delta1 = %s, delta2 = %s",
          delta1,
          delta2);
    }
  }

  static void checkMergeEpsilonAreEqual(double epsilon1, double epsilon2) {
    checkArgument(
        Double.compare(epsilon1, epsilon2) == 0,
        "Failed to merge: unequal values of epsilon. " + "epsilon1 = %s, epsilon2 = %s",
        epsilon1,
        epsilon2);
  }

  static void checkMergeBoundsAreEqual(double lower1, double lower2, double upper1, double upper2) {
    checkArgument(
        Double.compare(lower1, lower2) == 0,
        "Failed to merge: unequal lower bounds. " + "lower1 = %s, lower2 = %s",
        lower1,
        lower2);
    checkArgument(
        Double.compare(upper1, upper2) == 0,
        "Failed to merge: unequal upper bounds. " + "upper1 = %s, upper2 = %s",
        upper1,
        upper2);
  }

  static void checkMergeMaxContributionsPerPartitionAreEqual(
      int maxContributionsPerPartition1, int maxContributionsPerPartition2) {
    checkArgument(
        maxContributionsPerPartition1 == maxContributionsPerPartition2,
        "Failed to merge: unequal values of maxContributionsPerPartition. "
            + "maxContributionsPerPartition1 = %s, maxContributionsPerPartition2 = %s",
        maxContributionsPerPartition1,
        maxContributionsPerPartition2);
  }

  static void checkMergeMaxPartitionsContributedAreEqual(
      int maxPartitionsContributed1, int maxPartitionsContributed2) {
    checkArgument(
        maxPartitionsContributed1 == maxPartitionsContributed2,
        "Failed to merge: unequal values of maxPartitionsContributed. "
            + "maxPartitionsContributed1 = %s, maxPartitionsContributed2 = %s",
        maxPartitionsContributed1,
        maxPartitionsContributed2);
  }

  static void checkMergeMechanismTypesAreEqual(MechanismType type1, MechanismType type2) {
    checkArgument(
        Objects.equals(type1, type2),
        "Failed to merge: unequal mechanism types. type1 = %s, type2 = %s",
        type1,
        type2);
  }

  static void checkAlpha(double alpha) {
    checkArgument(
        0 < alpha && alpha < 1,
        "alpha should be strictly between 0 and 1. Provided value: %s",
        alpha);
  }

  static void checkNoiseComputeQuantileArguments(
      Noise noise,
      double rank,
      int l0Sensitivity,
      double lInfSensitivity,
      double epsilon,
      @Nullable Double delta) {
    checkSensitivities(l0Sensitivity, lInfSensitivity);
    checkEpsilon(epsilon);
    checkNoiseDelta(delta, noise);
    checkArgument(rank > 0 && rank < 1, "rank must be > 0 and < 1. Provided value: %s", rank);
  }
}
