/*
 * Copyright (C) 2018 The Android Open Source Project
 * Copyright (c) 2020 The Linux Foundation. All rights reserved.
 *
 * 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.
 */

#include <fcntl.h>
#include <log/log.h>
#include <pthread.h>
#include <sys/epoll.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <chrono>
#include <ctime>
#include <fstream>
#include <iomanip>
#include <memory>
#include <sstream>
#include <tuple>
#include <unordered_map>
#include <vector>

#include <display/drm/msm_drm_pp.h>
#include <xf86drm.h>
#include <xf86drmMode.h>

#include "histogram_collector.h"
#include "ringbuffer.h"

constexpr static auto implementation_defined_max_frame_ringbuffer = 300;

histogram::HistogramCollector::HistogramCollector()
    : histogram(histogram::Ringbuffer::create(implementation_defined_max_frame_ringbuffer,
                                              std::make_unique<histogram::DefaultTimeKeeper>())) {}

histogram::HistogramCollector::~HistogramCollector() {
  stop();
}

namespace {
static constexpr size_t numBuckets = 8;
static_assert((HIST_V_SIZE % numBuckets) == 0,
              "histogram cannot be rebucketed to smaller number of buckets");
static constexpr int bucket_compression = HIST_V_SIZE / numBuckets;

std::array<uint64_t, numBuckets> rebucketTo8Buckets(
    std::array<uint64_t, HIST_V_SIZE> const &frame) {
  std::array<uint64_t, numBuckets> bins;
  bins.fill(0);
  for (auto i = 0u; i < HIST_V_SIZE; i++)
    bins[i / bucket_compression] += frame[i];
  return bins;
}
}  // namespace

std::string histogram::HistogramCollector::Dump() const {
  uint64_t num_frames = 0;
  std::array<uint64_t, HIST_V_SIZE> all_sample_buckets;
  std::tie(num_frames, all_sample_buckets) = histogram->collect_cumulative();
  std::array<uint64_t, numBuckets> samples = rebucketTo8Buckets(all_sample_buckets);

  std::stringstream ss;
  ss << "Color Sampling, dark (0.0) to light (1.0): sampled frames: " << num_frames << '\n';
  if (num_frames == 0) {
    ss << "\tno color statistics collected\n";
    return ss.str();
  }

  ss << std::fixed << std::setprecision(3);
  ss << "\tbucket\t\t: # of displayed pixels at bucket value\n";
  for (auto i = 0u; i < samples.size(); i++) {
    ss << "\t" << i / static_cast<float>(samples.size()) << " to "
       << (i + 1) / static_cast<float>(samples.size()) << "\t: " << samples[i] << '\n';
  }

  return ss.str();
}

HWC2::Error histogram::HistogramCollector::collect(
    uint64_t max_frames, uint64_t timestamp,
    int32_t out_samples_size[NUM_HISTOGRAM_COLOR_COMPONENTS],
    uint64_t *out_samples[NUM_HISTOGRAM_COLOR_COMPONENTS], uint64_t *out_num_frames) const {
  if (!out_samples_size || !out_num_frames)
    return HWC2::Error::BadParameter;

  out_samples_size[0] = 0;
  out_samples_size[1] = 0;
  out_samples_size[2] = numBuckets;
  out_samples_size[3] = 0;

  uint64_t num_frames = 0;
  std::array<uint64_t, HIST_V_SIZE> samples;

  if (max_frames == 0 && timestamp == 0) {
    std::tie(num_frames, samples) = histogram->collect_cumulative();
  } else if (max_frames == 0) {
    std::tie(num_frames, samples) = histogram->collect_after(timestamp);
  } else if (timestamp == 0) {
    std::tie(num_frames, samples) = histogram->collect_max(max_frames);
  } else {
    std::tie(num_frames, samples) = histogram->collect_max_after(timestamp, max_frames);
  }

  auto samples_rebucketed = rebucketTo8Buckets(samples);
  *out_num_frames = num_frames;
  if (out_samples && out_samples[2])
    memcpy(out_samples[2], samples_rebucketed.data(), sizeof(uint64_t) * samples_rebucketed.size());

  return HWC2::Error::None;
}

HWC2::Error histogram::HistogramCollector::getAttributes(int32_t *format, int32_t *dataspace,
                                                         uint8_t *supported_components) const {
  if (!format || !dataspace || !supported_components)
    return HWC2::Error::BadParameter;

  *format = HAL_PIXEL_FORMAT_HSV_888;
  *dataspace = HAL_DATASPACE_UNKNOWN;
  *supported_components = HWC2_FORMAT_COMPONENT_2;
  return HWC2::Error::None;
}

void histogram::HistogramCollector::start() {
  start(implementation_defined_max_frame_ringbuffer);
}

void histogram::HistogramCollector::start(uint64_t max_frames) {
  std::unique_lock<decltype(mutex)> lk(mutex);
  if (started) {
    return;
  }

  started = true;
  histogram =
      histogram::Ringbuffer::create(max_frames, std::make_unique<histogram::DefaultTimeKeeper>());
  monitoring_thread = std::thread(&HistogramCollector::blob_processing_thread, this);
}

void histogram::HistogramCollector::stop() {
  std::unique_lock<decltype(mutex)> lk(mutex);
  if (!started) {
    return;
  }

  started = false;
  cv.notify_all();
  lk.unlock();

  if (monitoring_thread.joinable())
    monitoring_thread.join();
}

void histogram::HistogramCollector::notify_histogram_event(int blob_source_fd, BlobId id) {
  std::unique_lock<decltype(mutex)> lk(mutex);
  if (!started) {
    ALOGW("Discarding event blob-id: %X", id);
    return;
  }
  if (work_available) {
    ALOGI("notified of histogram event before consuming last one. prior event discarded");
  }

  work_available = true;
  blobwork = HistogramCollector::BlobWork{blob_source_fd, id};
  cv.notify_all();
}

void histogram::HistogramCollector::blob_processing_thread() {
  pthread_setname_np(pthread_self(), "histogram_blob");

  std::unique_lock<decltype(mutex)> lk(mutex);

  while (true) {
    cv.wait(lk, [this] { return !started || work_available; });
    if (!started) {
      return;
    }

    auto work = blobwork;
    work_available = false;
    lk.unlock();

    drmModePropertyBlobPtr blob = drmModeGetPropertyBlob(work.fd, work.id);
    if (!blob || !blob->data) {
      lk.lock();
      continue;
    }
    histogram->insert(*static_cast<struct drm_msm_hist *>(blob->data));
    drmModeFreePropertyBlob(blob);

    lk.lock();
  }
}
