/*
 *  Copyright 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

package org.webrtc;

import static java.lang.Math.abs;

import android.graphics.ImageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

@SuppressWarnings("deprecation")
public class CameraEnumerationAndroid {
  private final static String TAG = "CameraEnumerationAndroid";

  static final ArrayList<Size> COMMON_RESOLUTIONS = new ArrayList<Size>(Arrays.asList(
      // 0, Unknown resolution
      new Size(160, 120), // 1, QQVGA
      new Size(240, 160), // 2, HQVGA
      new Size(320, 240), // 3, QVGA
      new Size(400, 240), // 4, WQVGA
      new Size(480, 320), // 5, HVGA
      new Size(640, 360), // 6, nHD
      new Size(640, 480), // 7, VGA
      new Size(768, 480), // 8, WVGA
      new Size(854, 480), // 9, FWVGA
      new Size(800, 600), // 10, SVGA
      new Size(960, 540), // 11, qHD
      new Size(960, 640), // 12, DVGA
      new Size(1024, 576), // 13, WSVGA
      new Size(1024, 600), // 14, WVSGA
      new Size(1280, 720), // 15, HD
      new Size(1280, 1024), // 16, SXGA
      new Size(1920, 1080), // 17, Full HD
      new Size(1920, 1440), // 18, Full HD 4:3
      new Size(2560, 1440), // 19, QHD
      new Size(3840, 2160) // 20, UHD
      ));

  public static class CaptureFormat {
    // Class to represent a framerate range. The framerate varies because of lightning conditions.
    // The values are multiplied by 1000, so 1000 represents one frame per second.
    public static class FramerateRange {
      public int min;
      public int max;

      public FramerateRange(int min, int max) {
        this.min = min;
        this.max = max;
      }

      @Override
      public String toString() {
        return "[" + (min / 1000.0f) + ":" + (max / 1000.0f) + "]";
      }

      @Override
      public boolean equals(Object other) {
        if (!(other instanceof FramerateRange)) {
          return false;
        }
        final FramerateRange otherFramerate = (FramerateRange) other;
        return min == otherFramerate.min && max == otherFramerate.max;
      }

      @Override
      public int hashCode() {
        // Use prime close to 2^16 to avoid collisions for normal values less than 2^16.
        return 1 + 65537 * min + max;
      }
    }

    public final int width;
    public final int height;
    public final FramerateRange framerate;

    // TODO(hbos): If VideoCapturer.startCapture is updated to support other image formats then this
    // needs to be updated and VideoCapturer.getSupportedFormats need to return CaptureFormats of
    // all imageFormats.
    public final int imageFormat = ImageFormat.NV21;

    public CaptureFormat(int width, int height, int minFramerate, int maxFramerate) {
      this.width = width;
      this.height = height;
      this.framerate = new FramerateRange(minFramerate, maxFramerate);
    }

    public CaptureFormat(int width, int height, FramerateRange framerate) {
      this.width = width;
      this.height = height;
      this.framerate = framerate;
    }

    // Calculates the frame size of this capture format.
    public int frameSize() {
      return frameSize(width, height, imageFormat);
    }

    // Calculates the frame size of the specified image format. Currently only
    // supporting ImageFormat.NV21.
    // The size is width * height * number of bytes per pixel.
    // http://developer.android.com/reference/android/hardware/Camera.html#addCallbackBuffer(byte[])
    public static int frameSize(int width, int height, int imageFormat) {
      if (imageFormat != ImageFormat.NV21) {
        throw new UnsupportedOperationException("Don't know how to calculate "
            + "the frame size of non-NV21 image formats.");
      }
      return (width * height * ImageFormat.getBitsPerPixel(imageFormat)) / 8;
    }

    @Override
    public String toString() {
      return width + "x" + height + "@" + framerate;
    }

    @Override
    public boolean equals(Object other) {
      if (!(other instanceof CaptureFormat)) {
        return false;
      }
      final CaptureFormat otherFormat = (CaptureFormat) other;
      return width == otherFormat.width && height == otherFormat.height
          && framerate.equals(otherFormat.framerate);
    }

    @Override
    public int hashCode() {
      return 1 + (width * 65497 + height) * 251 + framerate.hashCode();
    }
  }

  // Helper class for finding the closest supported format for the two functions below. It creates a
  // comparator based on the difference to some requested parameters, where the element with the
  // minimum difference is the element that is closest to the requested parameters.
  private static abstract class ClosestComparator<T> implements Comparator<T> {
    // Difference between supported and requested parameter.
    abstract int diff(T supportedParameter);

    @Override
    public int compare(T t1, T t2) {
      return diff(t1) - diff(t2);
    }
  }

  // Prefer a fps range with an upper bound close to `framerate`. Also prefer a fps range with a low
  // lower bound, to allow the framerate to fluctuate based on lightning conditions.
  public static CaptureFormat.FramerateRange getClosestSupportedFramerateRange(
      List<CaptureFormat.FramerateRange> supportedFramerates, final int requestedFps) {
    return Collections.min(
        supportedFramerates, new ClosestComparator<CaptureFormat.FramerateRange>() {
          // Progressive penalty if the upper bound is further away than `MAX_FPS_DIFF_THRESHOLD`
          // from requested.
          private static final int MAX_FPS_DIFF_THRESHOLD = 5000;
          private static final int MAX_FPS_LOW_DIFF_WEIGHT = 1;
          private static final int MAX_FPS_HIGH_DIFF_WEIGHT = 3;

          // Progressive penalty if the lower bound is bigger than `MIN_FPS_THRESHOLD`.
          private static final int MIN_FPS_THRESHOLD = 8000;
          private static final int MIN_FPS_LOW_VALUE_WEIGHT = 1;
          private static final int MIN_FPS_HIGH_VALUE_WEIGHT = 4;

          // Use one weight for small `value` less than `threshold`, and another weight above.
          private int progressivePenalty(int value, int threshold, int lowWeight, int highWeight) {
            return (value < threshold) ? value * lowWeight
                                       : threshold * lowWeight + (value - threshold) * highWeight;
          }

          @Override
          int diff(CaptureFormat.FramerateRange range) {
            final int minFpsError = progressivePenalty(
                range.min, MIN_FPS_THRESHOLD, MIN_FPS_LOW_VALUE_WEIGHT, MIN_FPS_HIGH_VALUE_WEIGHT);
            final int maxFpsError = progressivePenalty(Math.abs(requestedFps * 1000 - range.max),
                MAX_FPS_DIFF_THRESHOLD, MAX_FPS_LOW_DIFF_WEIGHT, MAX_FPS_HIGH_DIFF_WEIGHT);
            return minFpsError + maxFpsError;
          }
        });
  }

  public static Size getClosestSupportedSize(
      List<Size> supportedSizes, final int requestedWidth, final int requestedHeight) {
    return Collections.min(supportedSizes, new ClosestComparator<Size>() {
      @Override
      int diff(Size size) {
        return abs(requestedWidth - size.width) + abs(requestedHeight - size.height);
      }
    });
  }

  // Helper method for camera classes.
  static void reportCameraResolution(Histogram histogram, Size resolution) {
    int index = COMMON_RESOLUTIONS.indexOf(resolution);
    // 0 is reserved for unknown resolution, so add 1.
    // indexOf returns -1 for unknown resolutions so it becomes 0 automatically.
    histogram.addSample(index + 1);
  }
}
