// 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 = consumed - produced;

    // 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
