/*
 * 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.datasketches.theta;

import org.testng.annotations.Test;

public class CornerCaseThetaSetOperationsTest {

  /* Hash Values
   * 9223372036854775807  Theta = 1.0
   *
   * 6730918654704304314  hash(3L)[0] >>> 1    GT_MIDP
   * 4611686018427387904  Theta for p = 0.5f = MIDP
   * 2206043092153046979  hash(2L)[0] >>> 1    LT_MIDP_V
   * 1498732507761423037  hash(5L)[0] >>> 1    LTLT_MIDP_V
   *
   * 1206007004353599230  hash(6L)[0] >>> 1    GT_LOWP_V
   *  922337217429372928  Theta for p = 0.1f = LOWP
   *  593872385995628096  hash(4L)[0] >>> 1    LT_LOWP_V
   *  405753591161026837  hash(1L)[0] >>> 1    LTLT_LOWP_V
   */

  private static final long GT_MIDP_V   = 3L;
  private static final float MIDP       = 0.5f;

  private static final long GT_LOWP_V   = 6L;
  private static final float LOWP       = 0.1f;
  private static final long LT_LOWP_V   = 4L;

  private static final double LOWP_THETA = LOWP;

  private enum SkType {
    EMPTY,      // { 1.0,  0, T} Bin: 101  Oct: 05
    EXACT,      // { 1.0, >0, F} Bin: 110  Oct: 06, specify only value
    ESTIMATION, // {<1.0, >0, F} Bin: 010  Oct: 02, specify only value
    DEGENERATE  // {<1.0,  0, F} Bin: 000  Oct: 0, specify p, value
  }

  //NOTE: 0 values in getSketch are not used.

  private static void checks(
      UpdateSketch thetaA,
      UpdateSketch thetaB,
      double resultInterTheta,
      int resultInterCount,
      boolean resultInterEmpty,
      double resultAnotbTheta,
      int resultAnotbCount,
      boolean resultAnotbEmpty) {
    CompactSketch csk;

    Intersection inter = SetOperation.builder().buildIntersection();

    csk = inter.intersect(thetaA, thetaB);
    checkResult("Intersect Stateless Theta, Theta", csk, resultInterTheta, resultInterCount, resultInterEmpty);
    csk = inter.intersect(thetaA.compact(), thetaB.compact());
    checkResult("Intersect Stateless Theta, Theta", csk, resultInterTheta, resultInterCount, resultInterEmpty);

    AnotB anotb = SetOperation.builder().buildANotB();

    csk = anotb.aNotB(thetaA, thetaB);
    checkResult("AnotB Stateless Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
    csk = anotb.aNotB(thetaA.compact(), thetaB.compact());
    checkResult("AnotB Stateless Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);

    anotb.setA(thetaA);
    anotb.notB(thetaB);
    csk = anotb.getResult(true);
    checkResult("AnotB Stateful Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);

    anotb.setA(thetaA.compact());
    anotb.notB(thetaB.compact());
    csk = anotb.getResult(true);
    checkResult("AnotB Stateful Theta, Theta", csk, resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }


  @Test
  public void emptyEmpty() {
    UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0);
    UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = true;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void emptyExact() {
    UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0);
    UpdateSketch thetaB = getSketch(SkType.EXACT, 0, GT_MIDP_V);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = true;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void emptyDegenerate() {
    UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0);
    UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = true;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void EmptyEstimation() {
    UpdateSketch thetaA = getSketch(SkType.EMPTY, 0, 0);
    UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = true;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  /*********************/

  @Test
  public void exactEmpty() {
    UpdateSketch thetaA = getSketch(SkType.EXACT, 0, GT_MIDP_V);
    UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 1;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void exactExact() {
    UpdateSketch thetaA = getSketch(SkType.EXACT, 0, GT_MIDP_V);
    UpdateSketch thetaB = getSketch(SkType.EXACT, 0, GT_MIDP_V);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 1;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = 1.0;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = true;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void exactDegenerate() {
    UpdateSketch thetaA = getSketch(SkType.EXACT, 0, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); //entries = 0
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 1;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void exactEstimation() {
    UpdateSketch thetaA = getSketch(SkType.EXACT, 0, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 1;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  /*********************/

  @Test
  public void estimationEmpty() {
    UpdateSketch thetaA = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 1;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void estimationExact() {
    UpdateSketch thetaA = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.EXACT, 0, LT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 1;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void estimationDegenerate() {
    UpdateSketch thetaA = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 1;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void estimationEstimation() {
    UpdateSketch thetaA = getSketch(SkType.ESTIMATION, MIDP, LT_LOWP_V);
    UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 1;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  /*********************/

  @Test
  public void DegenerateEmpty() {
    UpdateSketch thetaA = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V); //entries = 0
    UpdateSketch thetaB = getSketch(SkType.EMPTY, 0, 0);
    final double resultInterTheta = 1.0;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = true;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void DegenerateExact() {
    UpdateSketch thetaA = getSketch(SkType.DEGENERATE,  LOWP, GT_LOWP_V); //entries = 0
    UpdateSketch thetaB = getSketch(SkType.EXACT, 0, LT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void DegenerateDegenerate() {
    UpdateSketch thetaA = getSketch(SkType.DEGENERATE, MIDP, GT_MIDP_V); //entries = 0
    UpdateSketch thetaB = getSketch(SkType.DEGENERATE, LOWP, GT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  @Test
  public void DegenerateEstimation() {
    UpdateSketch thetaA = getSketch(SkType.DEGENERATE, MIDP, GT_MIDP_V); //entries = 0
    UpdateSketch thetaB = getSketch(SkType.ESTIMATION, LOWP, LT_LOWP_V);
    final double resultInterTheta = LOWP_THETA;
    final int resultInterCount = 0;
    final boolean resultInterEmpty = false;
    final double resultAnotbTheta = LOWP_THETA;
    final int resultAnotbCount = 0;
    final boolean resultAnotbEmpty = false;

    checks(thetaA, thetaB, resultInterTheta, resultInterCount, resultInterEmpty,
        resultAnotbTheta, resultAnotbCount, resultAnotbEmpty);
  }

  //=================================

  private static void checkResult(String comment, CompactSketch sk, double theta, int entries, boolean empty) {
    double skTheta = sk.getTheta();
    int skEntries = sk.getRetainedEntries();
    boolean skEmpty = sk.isEmpty();

    boolean thetaOk = skTheta == theta;
    boolean entriesOk = skEntries == entries;
    boolean emptyOk = skEmpty == empty;
    if (!thetaOk || !entriesOk || !emptyOk) {
      StringBuilder sb = new StringBuilder();
      sb.append(comment + ": ");
      if (!thetaOk)   { sb.append("Got: " + skTheta + ", Expected: " + theta + "; "); }
      if (!entriesOk) { sb.append("Got: " + skEntries + ", Expected: " + entries + "; "); }
      if (!emptyOk)   { sb.append("Got: " + skEmpty + ", Expected: " + empty + "."); }
      throw new IllegalArgumentException(sb.toString());
    }
  }

  private static UpdateSketch getSketch(SkType skType, float p, long value) {
    UpdateSketchBuilder bldr = UpdateSketch.builder();
    bldr.setLogNominalEntries(4);
    UpdateSketch sk;
    switch(skType) {
      case EMPTY: { // { 1.0,  0, T}
        sk = bldr.build();
        break;
      }
      case EXACT: { // { 1.0, >0, F}
        sk = bldr.build();
        sk.update(value);
        break;
      }
      case ESTIMATION: { // {<1.0, >0, F}
        bldr.setP(p);
        sk = bldr.build();
        sk.update(value);
        break;
      }
      case DEGENERATE: { // {<1.0,  0, F}
        bldr.setP(p);
        sk = bldr.build();
        sk.update(value);
        break;
      }

      default: { return null; } // should not happen
    }
    return sk;
  }

//  private static void println(Object o) {
//    System.out.println(o.toString());
//  }

//  @Test
//  public void printHash() {
//    long seed = DEFAULT_UPDATE_SEED;
//    long v = 6;
//    long hash = (hash(v, seed)[0]) >>> 1;
//    println(v + ", " + hash);
//  }

//  @Test
//  public void printPAsLong() {
//    float p = 0.5f;
//    println("p = " + p + ", " + (long)(Long.MAX_VALUE * p));
//  }

}
