# Copyright 2015 The Android Open Source Project
#
# 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.
"""Validate aspect ratio, crop and FoV vs format."""


import logging
import os.path
from mobly import test_runner
import numpy as np

import its_base_test
import camera_properties_utils
import capture_request_utils
import image_processing_utils
import image_fov_utils
import its_session_utils
import opencv_processing_utils

_ANDROID11_API_LEVEL = 30
_NAME = os.path.splitext(os.path.basename(__file__))[0]
_PREVIEW_SIZE = (1920, 1080)

# Before API level 30, only resolutions with the following listed aspect ratio
# are checked. Device launched after API level 30 will need to pass the test
# for all advertised resolutions. Device launched before API level 30 just
# needs to pass the test for all resolutions within these aspect ratios.
_AR_CHECKED_PRE_API_30 = ('4:3', '16:9', '18:9')
_AR_DIFF_ATOL = 0.01


def _check_skip_conditions(first_api_level, props):
  """Check the skip conditions based on first API level."""
  if first_api_level < _ANDROID11_API_LEVEL:  # Original constraint.
    camera_properties_utils.skip_unless(camera_properties_utils.read_3a(props))
  else:  # Loosen from read_3a to enable LIMITED coverage.
    camera_properties_utils.skip_unless(
        camera_properties_utils.ae_lock(props) and
        camera_properties_utils.awb_lock(props))


def _check_basic_correctness(cap, fmt_iter, w_iter, h_iter):
  """Check the capture for basic correctness."""
  if cap['format'] != fmt_iter:
    raise AssertionError
  if cap['width'] != w_iter:
    raise AssertionError
  if cap['height'] != h_iter:
    raise AssertionError


def _create_format_list():
  """Create format list for multiple capture objects.

  Do multi-capture of 'iter' and 'cmpr'. Iterate through all the available
  sizes of 'iter', and only use the size specified for 'cmpr'.
  The 'cmpr' capture is only used so that we have multiple capture target
  instead of just one, which should help catching more potential issues.
  The test doesn't look into the output of 'cmpr' images at all.
  The 'iter_max' or 'cmpr_size' key defines the maximal size being iterated
  or selected for the 'iter' and 'cmpr' stream accordingly. None means no
  upper bound is specified.

  Args:
    None

  Returns:
    format_list
  """
  format_list = []
  format_list.append({'iter': 'yuv', 'iter_max': None,
                      'cmpr': 'yuv', 'cmpr_size': _PREVIEW_SIZE})
  format_list.append({'iter': 'yuv', 'iter_max': _PREVIEW_SIZE,
                      'cmpr': 'jpeg', 'cmpr_size': None})
  format_list.append({'iter': 'yuv', 'iter_max': _PREVIEW_SIZE,
                      'cmpr': 'raw', 'cmpr_size': None})
  format_list.append({'iter': 'jpeg', 'iter_max': None,
                      'cmpr': 'raw', 'cmpr_size': None})
  format_list.append({'iter': 'jpeg', 'iter_max': None,
                      'cmpr': 'yuv', 'cmpr_size': _PREVIEW_SIZE})
  return format_list


def _print_failed_test_results(failed_ar, failed_fov, failed_crop,
                               first_api_level, level_3):
  """Print failed test results."""
  if failed_ar:
    logging.error('Aspect ratio test summary')
    logging.error('Images failed in the aspect ratio test:')
    logging.error('Aspect ratio value: width / height')
    for fa in failed_ar:
      logging.error('%s', fa)

  if failed_fov:
    logging.error('FoV test summary')
    logging.error('Images failed in the FoV test:')
    for fov in failed_fov:
      logging.error('%s', str(fov))

  if failed_crop:
    logging.error('Crop test summary')
    logging.error('Images failed in the crop test:')
    logging.error('Circle center (H x V) relative to the image center.')
    for fc in failed_crop:
      logging.error('%s', fc)
  if failed_ar:
    raise RuntimeError
  if failed_fov:
    raise RuntimeError
  if first_api_level > _ANDROID11_API_LEVEL:
    if failed_crop:  # failed_crop = [] if run_crop_test = False.
      raise RuntimeError
  else:
    if failed_crop and level_3:
      raise RuntimeError


def _is_checked_aspect_ratio(first_api_level, w, h):
  """Determine if format aspect ratio is a checked on based of first_API."""
  if first_api_level >= _ANDROID11_API_LEVEL:
    return True

  for ar_check in _AR_CHECKED_PRE_API_30:
    match_ar_list = [float(x) for x in ar_check.split(':')]
    match_ar = match_ar_list[0] / match_ar_list[1]
    if np.isclose(float(w) / h, match_ar, atol=_AR_DIFF_ATOL):
      return True

  return False


class AspectRatioAndCropTest(its_base_test.ItsBaseTest):
  """Test aspect ratio/field of view/cropping for each tested fmt combinations.

  This test checks for:
    1. Aspect ratio: images are not stretched
    2. Crop: center of images is not shifted
    3. FOV: images cropped to keep maximum possible FOV with only 1 dimension
       (horizontal or veritical) cropped.

  Aspect ratio and FOV test runs on level3, full and limited devices.
  Crop test only runs on level3 and full devices.

  The test chart is a black circle inside a black square. When raw capture is
  available, set the height vs. width ratio of the circle in the full-frame
  raw as ground truth. In an ideal setup such ratio should be very close to
  1.0, but here we just use the value derived from full resolution RAW as
  ground truth to account for the possibility that the chart is not well
  positioned to be precisely parallel to image sensor plane.
  The test then compares the ground truth ratio with the same ratio measured
  on images captued using different stream combinations of varying formats
  ('jpeg' and 'yuv') and resolutions.
  If raw capture is unavailable, a full resolution JPEG image is used to setup
  ground truth. In this case, the ground truth aspect ratio is defined as 1.0
  and it is the tester's responsibility to make sure the test chart is
  properly positioned so the detected circles indeed have aspect ratio close
  to 1.0 assuming no bugs causing image stretched.

  The aspect ratio test checks the aspect ratio of the detected circle and
  it will fail if the aspect ratio differs too much from the ground truth
  aspect ratio mentioned above.

  The FOV test examines the ratio between the detected circle area and the
  image size. When the aspect ratio of the test image is the same as the
  ground truth image, the ratio should be very close to the ground truth
  value. When the aspect ratio is different, the difference is factored in
  per the expectation of the Camera2 API specification, which mandates the
  FOV reduction from full sensor area must only occur in one dimension:
  horizontally or vertically, and never both. For example, let's say a sensor
  has a 16:10 full sensor FOV. For all 16:10 output images there should be no
  FOV reduction on them. For 16:9 output images the FOV should be vertically
  cropped by 9/10. For 4:3 output images the FOV should be cropped
  horizontally instead and the ratio (r) can be calculated as follows:
      (16 * r) / 10 = 4 / 3 => r = 40 / 48 = 0.8333
  Say the circle is covering x percent of the 16:10 sensor on the full 16:10
  FOV, and assume the circle in the center will never be cut in any output
  sizes (this can be achieved by picking the right size and position of the
  test circle), the from above cropping expectation we can derive on a 16:9
  output image the circle will cover (x / 0.9) percent of the 16:9 image; on
  a 4:3 output image the circle will cover (x / 0.8333) percent of the 4:3
  image.

  The crop test checks that the center of any output image remains aligned
  with center of sensor's active area, no matter what kind of cropping or
  scaling is applied. The test verifies that by checking the relative vector
  from the image center to the center of detected circle remains unchanged.
  The relative part is normalized by the detected circle size to account for
  scaling effect.
  """

  def test_aspect_ratio_and_crop(self):
    logging.debug('Starting %s', _NAME)
    failed_ar = []  # Streams failed the aspect ratio test.
    failed_crop = []  # Streams failed the crop test.
    failed_fov = []  # Streams that fail FoV test.
    format_list = _create_format_list()

    with its_session_utils.ItsSession(
        device_id=self.dut.serial,
        camera_id=self.camera_id,
        hidden_physical_id=self.hidden_physical_id) as cam:
      props = cam.get_camera_properties()
      fls_logical = props['android.lens.info.availableFocalLengths']
      logging.debug('logical available focal lengths: %s', str(fls_logical))
      props = cam.override_with_hidden_physical_camera_props(props)
      fls_physical = props['android.lens.info.availableFocalLengths']
      logging.debug('physical available focal lengths: %s', str(fls_physical))
      log_path = self.log_path
      if self.hidden_physical_id:
        logging.debug('Testing camera: %s.%s',
                      self.camera_id, self.hidden_physical_id)

      # Check SKIP conditions.
      first_api_level = its_session_utils.get_first_api_level(self.dut.serial)
      _check_skip_conditions(first_api_level, props)

      # Load chart for scene.
      its_session_utils.load_scene(
          cam, props, self.scene, self.tablet, self.chart_distance)

      # Determine camera capabilities.
      full_or_better = camera_properties_utils.full_or_better(props)
      level3 = camera_properties_utils.level3(props)
      raw_avlb = camera_properties_utils.raw16(props)
      debug = self.debug_mode

      req = capture_request_utils.auto_capture_request()

      # If raw available, use as ground truth.
      ref_img_name_stem = f'{os.path.join(log_path, _NAME)}'
      ref_fov, cc_ct_gt, aspect_ratio_gt = (
          image_fov_utils.find_fov_reference(
              cam, req, props, raw_avlb, ref_img_name_stem))

      run_crop_test = full_or_better and raw_avlb
      if run_crop_test:
        # Normalize the circle size to 1/4 of the image size, so that
        # circle size won't affect the crop test result
        crop_thresh_factor = ((min(ref_fov['w'], ref_fov['h']) / 4.0) /
                              max(ref_fov['circle_w'], ref_fov['circle_h']))
      else:
        logging.debug('Crop test skipped')

      # Take pictures of each settings with all the image sizes available.
      for fmt in format_list:
        fmt_iter = fmt['iter']
        fmt_cmpr = fmt['cmpr']
        # Get the size of 'cmpr'.
        sizes = capture_request_utils.get_available_output_sizes(
            fmt_cmpr, props, fmt['cmpr_size'])
        if not sizes:  # Device might not support RAW.
          continue
        w_cmpr, h_cmpr = sizes[0][0], sizes[0][1]
        for size_iter in capture_request_utils.get_available_output_sizes(
            fmt_iter, props, fmt['iter_max']):
          w_iter, h_iter = size_iter[0], size_iter[1]
          # Skip same format/size combination: ITS doesn't handle that properly.
          if w_iter*h_iter == w_cmpr*h_cmpr and fmt_iter == fmt_cmpr:
            continue
          out_surface = [{'width': w_iter, 'height': h_iter,
                          'format': fmt_iter}]
          out_surface.append({'width': w_cmpr, 'height': h_cmpr,
                              'format': fmt_cmpr})
          cam.do_3a()
          cap = cam.do_capture(req, out_surface)[0]
          _check_basic_correctness(cap, fmt_iter, w_iter, h_iter)
          logging.debug('Captured %s with %s %dx%d. Compared size: %dx%d',
                        fmt_iter, fmt_cmpr, w_iter, h_iter, w_cmpr, h_cmpr)
          img = image_processing_utils.convert_capture_to_rgb_image(cap)
          img *= 255  # cv2 uses [0, 255].
          img_name = '%s_%s_with_%s_w%d_h%d.png' % (
              os.path.join(log_path, _NAME), fmt_iter, fmt_cmpr, w_iter, h_iter)
          circle = opencv_processing_utils.find_circle(
              img, img_name, image_fov_utils.CIRCLE_MIN_AREA,
              image_fov_utils.CIRCLE_COLOR)
          if debug:
            opencv_processing_utils.append_circle_center_to_img(circle, img,
                                                                img_name)

          # Check pass/fail for fov coverage for all fmts in AR_CHECKED
          img /= 255  # image_processing_utils uses [0, 1].
          if _is_checked_aspect_ratio(first_api_level, w_iter, h_iter):
            fov_chk_msg = image_fov_utils.check_fov(
                circle, ref_fov, w_iter, h_iter)
            if fov_chk_msg:
              failed_fov.append(fov_chk_msg)
              image_processing_utils.write_image(img, img_name, True)

          # Check pass/fail for aspect ratio.
          ar_chk_msg = image_fov_utils.check_ar(
              circle, aspect_ratio_gt, w_iter, h_iter,
              f'{fmt_iter} with {fmt_cmpr}')
          if ar_chk_msg:
            failed_ar.append(ar_chk_msg)
            image_processing_utils.write_image(img, img_name, True)

          # Check pass/fail for crop.
          if run_crop_test:
            crop_chk_msg = image_fov_utils.check_crop(
                circle, cc_ct_gt, w_iter, h_iter,
                f'{fmt_iter} with {fmt_cmpr}', crop_thresh_factor)
            if crop_chk_msg:
              failed_crop.append(crop_chk_msg)
              image_processing_utils.write_image(img, img_name, True)

      # Print any failed test results.
      _print_failed_test_results(failed_ar, failed_fov, failed_crop,
                                 first_api_level, level3)

if __name__ == '__main__':
  test_runner.main()
