// Copyright 2017 The Fuchsia 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 <lib/affine/transform.h>
#include <lib/zx/clock.h>
#include <zircon/time.h>
#include <zircon/types.h>

#include <algorithm>
#include <cmath>
#include <limits>
#include <memory>

#include <audio-utils/audio-input.h>
#include <audio-utils/audio-stream.h>
#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>

namespace audio {
namespace utils {

static constexpr zx_duration_t CHUNK_TIME = ZX_MSEC(100);
static constexpr float MIN_DURATION = 0.100f;
static constexpr float MAX_DURATION = 86400.0f;

std::unique_ptr<AudioInput> AudioInput::Create(uint32_t dev_id) {
  fbl::AllocChecker ac;
  std::unique_ptr<AudioInput> res(new (&ac) AudioInput(dev_id));
  if (!ac.check())
    return nullptr;
  return res;
}

std::unique_ptr<AudioInput> AudioInput::Create(const char* dev_path) {
  fbl::AllocChecker ac;
  std::unique_ptr<AudioInput> res(new (&ac) AudioInput(dev_path));
  if (!ac.check())
    return nullptr;
  return res;
}

zx_status_t AudioInput::Record(AudioSink& sink, Duration duration) {
  auto res = RecordPrepare(sink);
  if (res != ZX_OK)
    return res;
  res = StartRingBuffer();
  if (res != ZX_OK) {
    printf("Failed to start capture (res %d)\n", res);
    return res;
  }
  return RecordToCompletion(sink, duration);
}

zx_status_t AudioInput::RecordPrepare(AudioSink& sink) {
  AudioStream::Format fmt = {
      .frame_rate = frame_rate_,
      .channels = static_cast<uint16_t>(channel_cnt_),
      .sample_format = sample_format_,
  };

  zx_status_t res = sink.SetFormat(fmt);
  if (res != ZX_OK) {
    printf("Failed to set sink format (rate %u, chan_count %u, fmt 0x%08x, res %d)\n", frame_rate_,
           channel_cnt_, sample_format_, res);
    return res;
  }

  uint64_t ring_bytes_64 = (zx_duration_mul_int64(CHUNK_TIME, frame_rate_) / ZX_SEC(1)) * frame_sz_;
  if (ring_bytes_64 > std::numeric_limits<uint32_t>::max()) {
    printf("Invalid frame rate %u\n", frame_rate_);
    return res;
  }

  uint32_t ring_bytes = static_cast<uint32_t>(ring_bytes_64);
  uint32_t ring_frames = ring_bytes / frame_sz_;

  res = GetBuffer(ring_frames, 8u);
  if (res != ZX_OK) {
    printf("Failed to establish ring buffer (%u frames, res %d)\n", ring_frames, res);
    return res;
  }

  return res;
}

zx_status_t AudioInput::RecordToCompletion(AudioSink& sink, Duration duration) {
  zx_status_t res = ZX_OK;
  long frames_expected = 0;
  int64_t bytes_expected = 0;
  const bool loop = std::holds_alternative<LoopingDoneCallback>(duration);
  if (!loop) {
    std::get<float>(duration) = std::clamp(std::get<float>(duration), MIN_DURATION, MAX_DURATION);
    printf("Recording for %.1f seconds\n", std::get<float>(duration));
    frames_expected = std::lround(frame_rate_ * std::get<float>(duration));
    bytes_expected = frame_sz_ * frames_expected;
  }

  uint32_t rd_ptr = 0;    // Our read ptr for the ring buffer.
  uint32_t wr_ptr = 0;    // Estimated write ptr in the ring buffer.
  uint32_t consumed = 0;  // Total bytes consumed.
  uint32_t produced = 0;  // Estimated total bytes produced.

  // A transformation from time to bytes captured safe to read. We wait until we have received about
  // 4 FIFOs before start reading to make sure we are behind the HW. We start the transformation at
  // -2 FIFOs and wake up after another 2 FIFOs.
  auto mono_to_safe_read_bytes = affine::Transform{static_cast<int64_t>(start_time_),
                                                   -2 * static_cast<int64_t>(fifo_depth_),
                                                   {frame_rate_ * frame_sz_, zx::sec(1).get()}};
  auto next_wake_time = zx::time(mono_to_safe_read_bytes.ApplyInverse(2 * fifo_depth_));

  // Repeat until looping is done or until consumed >= bytes_expected.
  while ((loop && std::get<LoopingDoneCallback>(duration)()) ||
         (!loop && consumed < bytes_expected)) {
    // We specify a floor to avoid not having a reasonable deadline per loop.
    constexpr auto kFloorWait = zx::msec(10);
    auto floor_wake_time = zx::clock::get_monotonic() + kFloorWait;
    if (next_wake_time < floor_wake_time) {
      next_wake_time = floor_wake_time;
    }
    zx::nanosleep(next_wake_time);
    auto safe_read = mono_to_safe_read_bytes.Apply(zx::clock::get_monotonic().get());

    if (loop) {
      consumed = static_cast<uint32_t>(safe_read) - (static_cast<uint32_t>(safe_read) % frame_sz_);
    } else {
      consumed = std::min(safe_read, bytes_expected);
    }
    uint32_t increment = fbl::round_down(consumed - produced, frame_sz_);

    // We want to process about 2 FIFOs worth of samples in each loop.
    next_wake_time = zx::time(mono_to_safe_read_bytes.ApplyInverse(safe_read + 2 * fifo_depth_));

    wr_ptr += increment;
    produced += increment;
    if (wr_ptr > rb_sz_) {
      wr_ptr -= rb_sz_;
    }

    uint32_t todo = wr_ptr + rb_sz_ - rd_ptr;
    if (todo >= rb_sz_) {
      todo -= rb_sz_;
    }

    ZX_DEBUG_ASSERT(todo < rb_sz_);
    ZX_DEBUG_ASSERT(rd_ptr < rb_sz_);

    uint32_t space = rb_sz_ - rd_ptr;
    uint32_t amt = std::min(space, todo);
    auto data = static_cast<const uint8_t*>(rb_virt_) + rd_ptr;

    res = zx_cache_flush(data, amt, ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
    if (res != ZX_OK) {
      printf("Failed to cache invalidate(res %d).\n", res);
      break;
    }

    res = sink.PutFrames(data, amt);
    if (res != ZX_OK) {
      printf("Failed to record %u bytes (res %d)\n", amt, res);
      break;
    }

    if (amt < todo) {
      amt = todo - amt;
      ZX_DEBUG_ASSERT(amt < rb_sz_);

      res = zx_cache_flush(rb_virt_, amt, ZX_CACHE_FLUSH_DATA | ZX_CACHE_FLUSH_INVALIDATE);
      if (res != ZX_OK) {
        printf("Failed to cache invalidate(res %d) %d\n", res, __LINE__);
        break;
      }

      res = sink.PutFrames(rb_virt_, amt);
      if (res != ZX_OK) {
        printf("Failed to record %u bytes (res %d)\n", amt, res);
        break;
      }

      rd_ptr = amt;
    } else {
      rd_ptr += amt;
      if (rd_ptr >= rb_sz_) {
        ZX_DEBUG_ASSERT(rd_ptr == rb_sz_);
        rd_ptr = 0;
      }
    }
  }

  StopRingBuffer();

  zx_status_t finalize_res = sink.Finalize();
  return (res == ZX_OK) ? finalize_res : res;
}

}  // namespace utils
}  // namespace audio
