// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "camera3_test/camera3_still_capture_fixture.h"

#include <algorithm>
#include <iterator>

#include <camera/camera_metadata.h>

#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/threading/platform_thread.h>
#include <base/time/time.h>

#include "cros-camera/common.h"

namespace camera3_test {

void Camera3StillCaptureFixture::SetUp() {
  ASSERT_EQ(
      0, cam_service_.Initialize(
             base::Bind(&Camera3StillCaptureFixture::ProcessStillCaptureResult,
                        base::Unretained(this)),
             Camera3Service::ProcessRecordingResultCallback()))
      << "Failed to initialize camera service";
  for (const auto& it : cam_ids_) {
    jpeg_max_sizes_[it] = cam_service_.GetStaticInfo(it)->GetJpegMaxSize();
  }
}

void Camera3StillCaptureFixture::ProcessStillCaptureResult(
    int cam_id,
    uint32_t frame_number,
    ScopedCameraMetadata metadata,
    cros::ScopedBufferHandle buffer) {
  VLOGF_ENTER();
  StillCaptureResult* result = &still_capture_results_[cam_id];
  result->result_metadatas.emplace_back(std::move(metadata));
  result->buffer_handles.emplace_back(std::move(buffer));

  time_t cur_time;
  time(&cur_time);
  result->result_date_time.push_back(cur_time);
  sem_post(&result->capture_result_sem);
}

int Camera3StillCaptureFixture::WaitStillCaptureResult(
    int cam_id, const struct timespec& timeout) {
  // Wait for capture result callback
  return sem_timedwait(&still_capture_results_[cam_id].capture_result_sem,
                       &timeout);
}

Camera3StillCaptureFixture::StillCaptureResult::StillCaptureResult() {
  sem_init(&capture_result_sem, 0, 0);
}

Camera3StillCaptureFixture::StillCaptureResult::~StillCaptureResult() {
  sem_destroy(&capture_result_sem);
}

// Test parameters:
// - Camera ID
class Camera3SimpleStillCaptureTest
    : public Camera3StillCaptureFixture,
      public ::testing::WithParamInterface<int32_t> {
 public:
  Camera3SimpleStillCaptureTest()
      : Camera3StillCaptureFixture(std::vector<int>(1, GetParam())),
        cam_id_(GetParam()) {}

 protected:
  using ExifTestData = Camera3ExifValidator::ExifTestData;

  void TakePictureTest(uint32_t num_still_pictures,
                       bool require_3a_converged = true,
                       bool enable_zsl = false);

  int cam_id_;
};

TEST_P(Camera3SimpleStillCaptureTest, JpegExifTest) {
  // Reference:
  // camera2/cts/StillCaptureTest.java.java#testJpegExif
  ResolutionInfo jpeg_resolution =
      cam_service_.GetStaticInfo(cam_id_)
          ->GetSortedOutputResolutions(HAL_PIXEL_FORMAT_BLOB)
          .back();
  std::vector<ResolutionInfo> thumbnail_resolutions;
  EXPECT_TRUE(cam_service_.GetStaticInfo(cam_id_)->GetAvailableThumbnailSizes(
                  &thumbnail_resolutions) == 0 &&
              !thumbnail_resolutions.empty())
      << "JPEG thumbnail sizes are not available";
  // Size must contain (0, 0).
  EXPECT_TRUE(std::find(thumbnail_resolutions.begin(),
                        thumbnail_resolutions.end(),
                        ResolutionInfo(0, 0)) != thumbnail_resolutions.end())
      << "JPEG thumbnail sizes should contain (0, 0)";
  // Each size must be distinct.
  EXPECT_EQ(thumbnail_resolutions.size(),
            std::set<ResolutionInfo>(thumbnail_resolutions.begin(),
                                     thumbnail_resolutions.end())
                .size())
      << "JPEG thumbnail sizes contain duplicate items";
  // Must be sorted in ascending order by area, by width if areas are same.
  EXPECT_TRUE(std::is_sorted(thumbnail_resolutions.begin(),
                             thumbnail_resolutions.end()))
      << "JPEG thumbnail sizes are not in ascending order";

  ResolutionInfo preview_resolution =
      cam_service_.GetStaticInfo(cam_id_)
          ->GetSortedOutputResolutions(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
          .back();
  ResolutionInfo recording_resolution(0, 0);
  ASSERT_EQ(
      0, cam_service_.StartPreview(cam_id_, preview_resolution, jpeg_resolution,
                                   recording_resolution));

  ExifTestData exif_test_data[] = {
      {thumbnail_resolutions.front(), 90, 80, 75},
      {thumbnail_resolutions.front(), 180, 90, 85},
      {thumbnail_resolutions.back(), 270, 100, 100},
  };

  ScopedCameraMetadata metadata(
      clone_camera_metadata(cam_service_.ConstructDefaultRequestSettings(
          cam_id_, CAMERA3_TEMPLATE_STILL_CAPTURE)));
  ASSERT_NE(nullptr, metadata.get())
      << "Failed to create still capture metadata";
  for (const auto& it : exif_test_data) {
#define ARRAY_SIZE(A) (sizeof(A) / sizeof(*(A)))
    int32_t thumbnail_resolution[] = {it.thumbnail_resolution.Width(),
                                      it.thumbnail_resolution.Height()};
    EXPECT_EQ(0,
              UpdateMetadata(ANDROID_JPEG_THUMBNAIL_SIZE, thumbnail_resolution,
                             ARRAY_SIZE(thumbnail_resolution), &metadata));
    EXPECT_EQ(0, UpdateMetadata(ANDROID_JPEG_ORIENTATION, &it.orientation, 1,
                                &metadata));
    EXPECT_EQ(0, UpdateMetadata(ANDROID_JPEG_QUALITY, &it.jpeg_quality, 1,
                                &metadata));
    EXPECT_EQ(0, UpdateMetadata(ANDROID_JPEG_THUMBNAIL_QUALITY,
                                &it.thumbnail_quality, 1, &metadata));
    cam_service_.TakeStillCapture(cam_id_, metadata.get());
  }

  struct timespec timeout;
  clock_gettime(CLOCK_REALTIME, &timeout);
  timeout.tv_sec += ARRAY_SIZE(exif_test_data);  // 1 second per capture
  for (size_t i = 0; i < std::size(exif_test_data); i++) {
    ASSERT_EQ(0, WaitStillCaptureResult(cam_id_, timeout))
        << "Waiting for still capture result timeout";
  }

  Camera3ExifValidator exif_test(*cam_service_.GetStaticInfo(cam_id_));
  for (size_t i = 0;
       i < still_capture_results_[cam_id_].result_metadatas.size(); i++) {
    exif_test.ValidateExifKeys(
        jpeg_resolution, exif_test_data[i],
        still_capture_results_[cam_id_].buffer_handles[i],
        jpeg_max_sizes_[cam_id_],
        *still_capture_results_[cam_id_].result_metadatas[i].get(),
        still_capture_results_[cam_id_].result_date_time[i]);
  }
  cam_service_.StopPreview(cam_id_);
}

void Camera3SimpleStillCaptureTest::TakePictureTest(uint32_t num_still_pictures,
                                                    bool require_3a_converged,
                                                    bool enable_zsl) {
  auto IsAFSupported = [this]() {
    std::vector<uint8_t> available_af_modes;
    cam_service_.GetStaticInfo(cam_id_)->GetAvailableAFModes(
        &available_af_modes);
    uint8_t af_modes[] = {ANDROID_CONTROL_AF_MODE_AUTO,
                          ANDROID_CONTROL_AF_MODE_CONTINUOUS_PICTURE,
                          ANDROID_CONTROL_AF_MODE_CONTINUOUS_VIDEO,
                          ANDROID_CONTROL_AF_MODE_MACRO};
    for (const auto& it : af_modes) {
      if (std::find(available_af_modes.begin(), available_af_modes.end(), it) !=
          available_af_modes.end()) {
        return true;
      }
    }
    return false;
  };

  ResolutionInfo jpeg_resolution =
      cam_service_.GetStaticInfo(cam_id_)
          ->GetSortedOutputResolutions(HAL_PIXEL_FORMAT_BLOB)
          .back();
  ResolutionInfo preview_resolution =
      cam_service_.GetStaticInfo(cam_id_)
          ->GetSortedOutputResolutions(HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED)
          .back();
  ResolutionInfo recording_resolution(0, 0);
  ASSERT_EQ(
      0, cam_service_.StartPreview(cam_id_, preview_resolution, jpeg_resolution,
                                   recording_resolution));

  // Trigger an auto focus run, and wait for AF locked.
  if (IsAFSupported()) {
    cam_service_.StartAutoFocus(cam_id_);
    int af_result = cam_service_.WaitForAutoFocusDone(cam_id_);
    if (require_3a_converged) {
      ASSERT_EQ(0, af_result) << "Wait for auto focus done timed out";
    } else if (af_result != 0) {
      LOGF(WARNING) << "Ignore AF converged timeout failure.";
    }
  }
  // Wait for AWB converged, then lock it.
  int awb_result = cam_service_.WaitForAWBConvergedAndLock(cam_id_);
  if (require_3a_converged) {
    ASSERT_EQ(0, awb_result) << "Wait for AWB converged timed out";
  } else if (awb_result != 0) {
    LOGF(WARNING) << "Ignore AWB converged timeout failure.";
  }
  // Trigger an AE precapture metering sequence and wait for AE converged.
  cam_service_.StartAEPrecapture(cam_id_);
  int ae_result = cam_service_.WaitForAEStable(cam_id_);
  if (require_3a_converged) {
    ASSERT_EQ(0, ae_result) << "Wait for AE stable timed out";
  } else if (ae_result != 0) {
    LOGF(WARNING) << "Ignore AE converged timeout failure.";
  }

  const camera_metadata_t* metadata =
      cam_service_.ConstructDefaultRequestSettings(
          cam_id_, CAMERA3_TEMPLATE_STILL_CAPTURE);
  if (enable_zsl) {
    android::CameraMetadata zsl_metadata(clone_camera_metadata(metadata));
    uint8_t enable_zsl = 1;
    ASSERT_EQ(zsl_metadata.update(ANDROID_CONTROL_ENABLE_ZSL, &enable_zsl, 1),
              0);
    auto* raw_zsl_metadata = zsl_metadata.getAndLock();
    for (uint32_t i = 0; i < num_still_pictures; i++) {
      cam_service_.TakeStillCapture(cam_id_, raw_zsl_metadata);

      // Take a brief pause to allow ZSL to accumulate raw buffers that can be
      // selected for private reprocessing.
      base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
    }
    zsl_metadata.unlock(raw_zsl_metadata);
  } else {
    for (uint32_t i = 0; i < num_still_pictures; i++) {
      cam_service_.TakeStillCapture(cam_id_, metadata);
    }
  }

  cam_service_.StopPreview(cam_id_);
}

TEST_P(Camera3SimpleStillCaptureTest, TakePictureTest) {
  TakePictureTest(1);
}

TEST_P(Camera3SimpleStillCaptureTest, PerformanceTest) {
  TakePictureTest(2);
}

TEST_P(Camera3SimpleStillCaptureTest, TakePictureZslTest) {
  if (!cam_service_.GetStaticInfo(cam_id_)->HasAvailableRequestKey(
          ANDROID_CONTROL_ENABLE_ZSL)) {
    GTEST_SKIP();
  }
  TakePictureTest(10, /*require_3a_converged=*/true, /*enable_zsl=*/true);
}

// Test parameters:
// - Camera ID
class Camera3DumpSimpleStillCaptureTest : public Camera3SimpleStillCaptureTest {
 public:
  Camera3DumpSimpleStillCaptureTest() : dump_path_(GetCommandLineDumpPath()) {}

  void ProcessStillCaptureResult(int cam_id,
                                 uint32_t frame_number,
                                 ScopedCameraMetadata metadata,
                                 cros::ScopedBufferHandle buffer) override;

 protected:
  base::FilePath dump_path_;

  inline base::FilePath GetCommandLineDumpPath() {
    return base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
        "dump_still_capture_path");
  }
};

void Camera3DumpSimpleStillCaptureTest::ProcessStillCaptureResult(
    int cam_id,
    uint32_t frame_number,
    ScopedCameraMetadata metadata,
    cros::ScopedBufferHandle buffer) {
  size_t jpeg_max_size = jpeg_max_sizes_[cam_id_];
  void* buf_addr = nullptr;
  ASSERT_EQ(0, Camera3TestGralloc::GetInstance()->Lock(
                   *buffer, 0, 0, 0, jpeg_max_size, 1, &buf_addr));
  ASSERT_NE(nullptr, buf_addr);

  {
    // Ensure buffer unlock process is executed when exiting from ASSERT_XX.
    struct UnlockBuf {
      void operator()(buffer_handle_t* handle) {
        Camera3TestGralloc::GetInstance()->Unlock(*handle);
      }
    };
    std::unique_ptr<buffer_handle_t, UnlockBuf> unlock(buffer.get());

    auto jpeg_blob = reinterpret_cast<camera3_jpeg_blob_t*>(
        static_cast<uint8_t*>(buf_addr) + jpeg_max_size -
        sizeof(camera3_jpeg_blob_t));
    ASSERT_LE(buf_addr, static_cast<void*>(jpeg_blob));
    ASSERT_EQ(CAMERA3_JPEG_BLOB_ID, jpeg_blob->jpeg_blob_id);

    auto jpeg_size = jpeg_blob->jpeg_size;
    ASSERT_EQ(jpeg_size,
              base::WriteFile(dump_path_, static_cast<const char*>(buf_addr),
                              jpeg_size));
  }
}

TEST_P(Camera3DumpSimpleStillCaptureTest, DumpCaptureResult) {
  // Run only if --dump_still_capture_path argument presented.
  if (dump_path_.empty()) {
    GTEST_SKIP();
  }
  TakePictureTest(1, /*require_3a_converged=*/false);
}

// Test parameters:
// - Camera ID, preview resolution, JPEG resolution
class Camera3JpegResolutionTest
    : public Camera3StillCaptureFixture,
      public ::testing::WithParamInterface<
          std::tuple<int32_t, ResolutionInfo, ResolutionInfo>> {
 public:
  Camera3JpegResolutionTest()
      : Camera3StillCaptureFixture(
            std::vector<int>(1, std::get<0>(GetParam()))),
        cam_id_(std::get<0>(GetParam())) {}

 protected:
  int cam_id_;
};

TEST_P(Camera3JpegResolutionTest, JpegResolutionTest) {
  ResolutionInfo preview_resolution(std::get<1>(GetParam()));
  ResolutionInfo jpeg_resolution(std::get<2>(GetParam()));
  VLOGF(1) << "Device " << cam_id_;
  VLOGF(1) << "Preview resolution " << preview_resolution.Width() << "x"
           << preview_resolution.Height();
  VLOGF(1) << "JPEG resolution " << jpeg_resolution.Width() << "x"
           << jpeg_resolution.Height();

  ResolutionInfo recording_resolution(0, 0);
  ASSERT_EQ(
      0, cam_service_.StartPreview(cam_id_, preview_resolution, jpeg_resolution,
                                   recording_resolution));
  ScopedCameraMetadata metadata(
      clone_camera_metadata(cam_service_.ConstructDefaultRequestSettings(
          cam_id_, CAMERA3_TEMPLATE_STILL_CAPTURE)));
  ASSERT_NE(nullptr, metadata.get())
      << "Failed to create still capture metadata";
  cam_service_.TakeStillCapture(cam_id_, metadata.get());
  cam_service_.StopPreview(cam_id_);

  ASSERT_EQ(1, still_capture_results_[cam_id_].buffer_handles.size())
      << "Incorrect number of still captures received";
  JpegExifInfo jpeg_exif_info(still_capture_results_[cam_id_].buffer_handles[0],
                              jpeg_max_sizes_[cam_id_]);
  ASSERT_TRUE(jpeg_exif_info.Initialize());
  EXPECT_EQ(jpeg_resolution, jpeg_exif_info.jpeg_resolution)
      << "JPEG size result and request should match";
}

INSTANTIATE_TEST_SUITE_P(
    Camera3StillCaptureTest,
    Camera3SimpleStillCaptureTest,
    ::testing::ValuesIn(Camera3Module().GetTestCameraIds()));

static std::vector<std::tuple<int, ResolutionInfo, ResolutionInfo>>
IterateCameraIdPreviewJpegResolution() {
  std::vector<std::tuple<int, ResolutionInfo, ResolutionInfo>> result;
  auto cam_ids = Camera3Module().GetTestCameraIds();
  for (const auto& cam_id : cam_ids) {
    auto preview_resolutions = Camera3Module().GetSortedOutputResolutions(
        cam_id, HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
    auto jpeg_resolutions = Camera3Module().GetSortedOutputResolutions(
        cam_id, HAL_PIXEL_FORMAT_BLOB);
    for (const auto& preview_resolution : preview_resolutions) {
      for (const auto& jpeg_resolution : jpeg_resolutions) {
        result.emplace_back(cam_id, preview_resolution, jpeg_resolution);
      }
    }
  }
  return result;
}

INSTANTIATE_TEST_SUITE_P(
    Camera3StillCaptureTest,
    Camera3JpegResolutionTest,
    ::testing::ValuesIn(IterateCameraIdPreviewJpegResolution()));

INSTANTIATE_TEST_SUITE_P(
    Camera3StillCaptureTest,
    Camera3DumpSimpleStillCaptureTest,
    ::testing::ValuesIn(Camera3Module().GetTestCameraIds()));

}  // namespace camera3_test
