/*
 * Copyright (C) 2010 The Guava Authors
 *
 * 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.common.collect;

import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import com.google.caliper.Param;
import com.google.common.base.Function;
import java.math.BigInteger;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;

/**
 * Benchmarks to compare performance of MinMaxPriorityQueue and PriorityQueue.
 *
 * @author Sverre Sundsdal
 */
public class MinMaxPriorityQueueBenchmark {
  @Param private ComparatorType comparator;

  // TODO(kevinb): add 1000000 back when we have the ability to throw
  // NotApplicableException in the expensive comparator case.
  @Param({"100", "10000"})
  private int size;

  @Param private HeapType heap;

  private Queue<Integer> queue;

  private final Random random = new Random();

  @BeforeExperiment
  void setUp() {
    queue = heap.create(comparator.get());
    for (int i = 0; i < size; i++) {
      queue.add(random.nextInt());
    }
  }

  @Benchmark
  void pollAndAdd(int reps) {
    for (int i = 0; i < reps; i++) {
      // TODO(kevinb): precompute random #s?
      queue.add(queue.poll() ^ random.nextInt());
    }
  }

  @Benchmark
  void populate(int reps) {
    for (int i = 0; i < reps; i++) {
      queue.clear();
      for (int j = 0; j < size; j++) {
        // TODO(kevinb): precompute random #s?
        queue.add(random.nextInt());
      }
    }
  }

  /**
   * Implementation of the InvertedMinMaxPriorityQueue which forwards all calls to a
   * MinMaxPriorityQueue, except poll, which is forwarded to pollMax. That way we can benchmark
   * pollMax using the same code that benchmarks poll.
   */
  static final class InvertedMinMaxPriorityQueue<T> extends ForwardingQueue<T> {
    MinMaxPriorityQueue<T> mmHeap;

    public InvertedMinMaxPriorityQueue(Comparator<T> comparator) {
      mmHeap = MinMaxPriorityQueue.orderedBy(comparator).create();
    }

    @Override
    protected Queue<T> delegate() {
      return mmHeap;
    }

    @Override
    public T poll() {
      return mmHeap.pollLast();
    }
  }

  public enum HeapType {
    MIN_MAX {
      @Override
      public Queue<Integer> create(Comparator<Integer> comparator) {
        return MinMaxPriorityQueue.orderedBy(comparator).create();
      }
    },
    PRIORITY_QUEUE {
      @Override
      public Queue<Integer> create(Comparator<Integer> comparator) {
        return new PriorityQueue<>(11, comparator);
      }
    },
    INVERTED_MIN_MAX {
      @Override
      public Queue<Integer> create(Comparator<Integer> comparator) {
        return new InvertedMinMaxPriorityQueue<>(comparator);
      }
    };

    public abstract Queue<Integer> create(Comparator<Integer> comparator);
  }

  /**
   * Does a CPU intensive operation on Integer and returns a BigInteger Used to implement an
   * ordering that spends a lot of cpu.
   */
  static class ExpensiveComputation implements Function<Integer, BigInteger> {
    @Override
    public BigInteger apply(Integer from) {
      BigInteger v = BigInteger.valueOf(from);
      // Math.sin is very slow for values outside 4*pi
      // Need to take absolute value to avoid inverting the value.
      for (double i = 0; i < 100; i += 20) {
        v =
            v.add(
                v.multiply(
                    BigInteger.valueOf(((Double) Math.abs(Math.sin(i) * 10.0)).longValue())));
      }
      return v;
    }
  }

  public enum ComparatorType {
    CHEAP {
      @Override
      public Comparator<Integer> get() {
        return Ordering.natural();
      }
    },
    EXPENSIVE {
      @Override
      public Comparator<Integer> get() {
        return Ordering.natural().onResultOf(new ExpensiveComputation());
      }
    };

    public abstract Comparator<Integer> get();
  }
}
