// 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 <fcntl.h>
#include <fuchsia/hardware/audio/llcpp/fidl.h>
#include <inttypes.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fdio.h>
#include <lib/zx/channel.h>
#include <lib/zx/clock.h>
#include <lib/zx/handle.h>
#include <lib/zx/vmar.h>
#include <lib/zx/vmo.h>
#include <stdio.h>
#include <string.h>
#include <zircon/assert.h>
#include <zircon/device/audio.h>
#include <zircon/process.h>
#include <zircon/syscalls.h>
#include <zircon/time.h>
#include <zircon/types.h>

#include <limits>

#include <audio-proto-utils/format-utils.h>
#include <audio-utils/audio-device-stream.h>
#include <audio-utils/audio-input.h>
#include <audio-utils/audio-output.h>
#include <fbl/algorithm.h>
#include <fbl/auto_call.h>
#include <fbl/unique_fd.h>

namespace audio {
namespace utils {

AudioDeviceStream::AudioDeviceStream(StreamDirection direction, uint32_t dev_id)
    : direction_(direction) {
  snprintf(name_, sizeof(name_), "/dev/class/audio-%s-2/%03u",
           direction == StreamDirection::kInput ? "input" : "output", dev_id);
}

AudioDeviceStream::AudioDeviceStream(StreamDirection direction, const char* dev_path)
    : direction_(direction) {
  strncpy(name_, dev_path, sizeof(name_) - 1);
  name_[sizeof(name_) - 1] = 0;
}

AudioDeviceStream::~AudioDeviceStream() { Close(); }

zx_status_t AudioDeviceStream::Open() {
  if (stream_ch_ != ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  zx::channel local, remote;
  auto res = zx::channel::create(0, &local, &remote);
  if (res != ZX_OK) {
    printf("Failed to create channel (res %d)\n", res);
    return res;
  }
  res = fdio_service_connect(name(), remote.release());
  if (res != ZX_OK) {
    printf("Failed to obtain channel (res %d)\n", res);
    return res;
  }
  audio_fidl::Device::SyncClient client_wrap(std::move(local));
  audio_fidl::Device::ResultOf::GetChannel channel_wrap = client_wrap.GetChannel();
  if (!channel_wrap.ok()) {
    res = channel_wrap.status();
    printf("GetChannel failed with error %s (res %d)\n", channel_wrap.error(), res);
    return res;
  }

  stream_ch_ = std::move(channel_wrap->channel);
  return ZX_OK;
}

zx_status_t AudioDeviceStream::GetSupportedFormats(const SupportedFormatsCallback& cb) const {
  auto formats =
      audio_fidl::StreamConfig::Call::GetSupportedFormats(zx::unowned_channel(stream_ch_));
  for (auto& i : formats->supported_formats) {
    cb(i);
  }
  return ZX_OK;
}

zx_status_t AudioDeviceStream::WatchPlugState(
    audio_stream_cmd_plug_detect_resp_t* out_state) const {
  ZX_DEBUG_ASSERT(out_state != nullptr);
  auto prop = audio_fidl::StreamConfig::Call::GetProperties(zx::unowned_channel(stream_ch_));
  if (prop.status() != ZX_OK) {
    printf("Failed to get properties to watch plug state (res %d)\n", prop.status());
    return prop.status();
  }

  auto state = audio_fidl::StreamConfig::Call::WatchPlugState(zx::unowned_channel(stream_ch_));
  if (state.status() != ZX_OK) {
    printf("Failed to watch plug state (res %d)\n", state.status());
    return state.status();
  }

  if (prop->properties.plug_detect_capabilities() ==
      audio_fidl::PlugDetectCapabilities::CAN_ASYNC_NOTIFY) {
    out_state->plug_state_time = state->plug_state.plug_state_time();
    out_state->flags = state->plug_state.plugged() ? AUDIO_PDNF_PLUGGED : 0;
    out_state->flags |= AUDIO_PDNF_CAN_NOTIFY;
  } else {
    out_state->flags = AUDIO_PDNF_PLUGGED;
    out_state->flags |= AUDIO_PDNF_HARDWIRED;
  }
  return ZX_OK;
}

zx_status_t AudioDeviceStream::SetMute(bool mute) {
  muted_ = mute;
  return SetGainParams();
}

zx_status_t AudioDeviceStream::SetAgc(bool enabled) {
  agc_enabled_ = enabled;
  return SetGainParams();
}

zx_status_t AudioDeviceStream::SetGain(float gain) {
  gain_ = gain;
  return SetGainParams();
}

zx_status_t AudioDeviceStream::SetGainParams() {
  auto builder = audio_fidl::GainState::UnownedBuilder();
  fidl::aligned<bool> muted = muted_;
  fidl::aligned<bool> agc_enabled = agc_enabled_;
  fidl::aligned<float> gain = gain_;
  builder.set_muted(fidl::unowned_ptr(&muted));
  builder.set_agc_enabled(fidl::unowned_ptr(&agc_enabled));
  builder.set_gain_db(fidl::unowned_ptr(&gain));
  audio_fidl::StreamConfig::Call::SetGain(zx::unowned_channel(stream_ch_), builder.build());
  return ZX_OK;
}

zx_status_t AudioDeviceStream::WatchGain(audio_stream_cmd_get_gain_resp_t* out_gain) const {
  auto prop = audio_fidl::StreamConfig::Call::GetProperties(zx::unowned_channel(stream_ch_));
  if (prop.status() == ZX_OK) {
    out_gain->min_gain = prop->properties.min_gain_db();
    out_gain->max_gain = prop->properties.max_gain_db();
    out_gain->gain_step = prop->properties.gain_step_db();
  } else {
    printf("Failed to get properties to watch gainstate (res %d)\n", prop.status());
    return prop.status();
  }

  auto gain_state = audio_fidl::StreamConfig::Call::WatchGainState(zx::unowned_channel(stream_ch_));
  if (gain_state.status() == ZX_OK) {
    out_gain->cur_gain = gain_state->gain_state.gain_db();
    out_gain->can_mute = gain_state->gain_state.has_muted();
    if (gain_state->gain_state.has_muted()) {
      out_gain->cur_mute = gain_state->gain_state.muted();
    }
    out_gain->can_agc = gain_state->gain_state.has_agc_enabled();
    if (gain_state->gain_state.has_agc_enabled()) {
      out_gain->cur_mute = gain_state->gain_state.agc_enabled();
    }
  } else {
    printf("Failed to watch gain state (res %d)\n", gain_state.status());
    return gain_state.status();
  }

  return ZX_OK;
}

zx_status_t AudioDeviceStream::GetUniqueId(audio_stream_cmd_get_unique_id_resp_t* out_id) const {
  if (out_id == nullptr)
    return ZX_ERR_INVALID_ARGS;
  auto result = audio_fidl::StreamConfig::Call::GetProperties(zx::unowned_channel(stream_ch_));
  size_t size = (result->properties.unique_id().size() > sizeof(out_id->unique_id))
                    ? sizeof(out_id->unique_id)
                    : result->properties.unique_id().size();
  memcpy(out_id->unique_id.data, result->properties.unique_id().data(), size);
  return ZX_OK;
}

zx_status_t AudioDeviceStream::GetString(audio_stream_string_id_t id,
                                         audio_stream_cmd_get_string_resp_t* out_str) const {
  if (out_str == nullptr)
    return ZX_ERR_INVALID_ARGS;

  auto result = audio_fidl::StreamConfig::Call::GetProperties(zx::unowned_channel(stream_ch_));
  switch (id) {
    case AUDIO_STREAM_STR_ID_MANUFACTURER:
      out_str->strlen = static_cast<uint32_t>(result->properties.manufacturer().size());
      memcpy(out_str->str, result->properties.manufacturer().data(), out_str->strlen);
      break;
    case AUDIO_STREAM_STR_ID_PRODUCT:
      out_str->strlen = static_cast<uint32_t>(result->properties.product().size());
      memcpy(out_str->str, result->properties.product().data(), out_str->strlen);
      break;
    default:
      return ZX_ERR_INVALID_ARGS;
  }
  return ZX_OK;
}

zx_status_t AudioDeviceStream::PlugMonitor(float duration, PlugMonitorCallback* monitor) {
  const double duration_ns = static_cast<double>(duration) * ZX_SEC(1);
  const zx_time_t deadline = zx_deadline_after(static_cast<zx_duration_t>(duration_ns));
  zx_time_t last_plug_time = zx::clock::get_monotonic().get();
  while (true) {
    // TODO(andresoportus): Currently if no plug state changes occur, we wait forever.
    // Once LLCPP supports async clients, stop monitoring even when there is no plug state change.
    audio_stream_cmd_plug_detect_resp_t out_state = {};
    auto status = WatchPlugState(&out_state);
    if (status != ZX_OK) {
      printf("Failed to watch plug state (res %d)\n", status);
      return status;
    }
    zx_time_t plug_time = out_state.plug_state_time;
    printf("Plug State now : %s (%.3lf sec since last change).\n",
           out_state.flags & AUDIO_PDNF_PLUGGED ? "plugged" : "unplugged",
           static_cast<double>(zx_time_sub_time(plug_time, last_plug_time)) /
               static_cast<double>(zx::sec(1).get()));

    if (out_state.flags & AUDIO_PDNF_HARDWIRED) {
      printf("Stream reports that it is hardwired, Monitoring is not possible.\n");
      return ZX_OK;
    }
    if (monitor) {
      return (*monitor)(out_state.flags & AUDIO_PDNF_PLUGGED, plug_time);
    }
    if (zx::clock::get_monotonic().get() > deadline) {
      break;
    }
  }
  printf("Monitoring finished.\n");
  return ZX_OK;
}

zx_status_t AudioDeviceStream::SetFormat(uint32_t frames_per_second, uint16_t channels,
                                         uint64_t channels_to_use_bitmask,
                                         audio_sample_format_t sample_format) {
  if ((stream_ch_ == ZX_HANDLE_INVALID) || (rb_ch_ != ZX_HANDLE_INVALID))
    return ZX_ERR_BAD_STATE;

  auto sizes = audio::utils::GetSampleSizes(sample_format);
  sample_size_ = sizes.valid_bits_per_sample;
  channel_size_ = 8 * sizes.bytes_per_sample;

  if (sample_size_ == 0 || channel_size_ == 0) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  channel_cnt_ = channels;
  frame_sz_ = channels * channel_size_ / 8;
  frame_rate_ = frames_per_second;
  sample_format_ = sample_format;

  zx::channel local, remote;
  auto status = zx::channel::create(0, &local, &remote);
  if (status != ZX_OK) {
    return status;
  }

  audio_fidl::PcmFormat pcm_format = {};
  pcm_format.number_of_channels = static_cast<uint8_t>(channel_cnt_);
  pcm_format.channels_to_use_bitmask = channels_to_use_bitmask;
  pcm_format.sample_format = audio_fidl::SampleFormat::PCM_SIGNED;
  pcm_format.frame_rate = frames_per_second;
  pcm_format.bytes_per_sample = channel_size_ / 8;
  pcm_format.valid_bits_per_sample = sample_size_;
  auto builder = audio_fidl::Format::UnownedBuilder();
  builder.set_pcm_format(fidl::unowned_ptr(&pcm_format));

  audio_fidl::StreamConfig::Call::CreateRingBuffer(zx::unowned_channel(stream_ch_), builder.build(),
                                                   std::move(remote));
  rb_ch_ = std::move(local);
  return ZX_OK;
}

zx_status_t AudioDeviceStream::GetBuffer(uint32_t frames, uint32_t irqs_per_ring) {
  zx_status_t res;

  if (!frames)
    return ZX_ERR_INVALID_ARGS;

  if (!rb_ch_.is_valid() || rb_vmo_.is_valid() || !frame_sz_) {
    return ZX_ERR_BAD_STATE;
  }

  // Stash the FIFO depth, in case users need to know it.
  {
    auto result = audio_fidl::RingBuffer::Call::GetProperties(zx::unowned_channel(rb_ch_));
    if (result.status() != ZX_OK) {
      return ZX_ERR_BAD_STATE;
    }
    fifo_depth_ = result->properties.fifo_depth();
    external_delay_nsec_ = result->properties.external_delay();
  }

  // Get a VMO representing the ring buffer we will share with the audio driver.
  // fast_capture_notifications not supported (set to an invalid channel).
  // fast_playback_notifications not supported (set to an invalid channel).
  auto result =
      audio_fidl::RingBuffer::Call::GetVmo(zx::unowned_channel(rb_ch_), frames, irqs_per_ring);
  uint64_t rb_sz = static_cast<uint64_t>(result->result.response().num_frames) * frame_sz_;
  rb_vmo_ = std::move(result->result.mutable_response().ring_buffer);

  // We have the buffer, fetch the underlying size of the VMO (a rounded up
  // multiple of pages) and sanity check it against the effective size the
  // driver reported.
  uint64_t rb_page_sz;
  res = rb_vmo_.get_size(&rb_page_sz);
  if (res != ZX_OK) {
    printf("Failed to fetch ring buffer VMO size (res %d)\n", res);
    return res;
  }

  if ((rb_sz > std::numeric_limits<decltype(rb_sz_)>::max()) || (rb_sz > rb_page_sz)) {
    printf(
        "Bad ring buffer size returned by audio driver! "
        "(kernel size = %lu driver size = %lu)\n",
        rb_page_sz, rb_sz);
    return ZX_ERR_INVALID_ARGS;
  }

  rb_sz_ = static_cast<decltype(rb_sz_)>(rb_sz);

  // Map the VMO into our address space
  // TODO(johngro) : How do I specify the cache policy for this mapping?
  uint32_t flags = input() ? ZX_VM_PERM_READ : ZX_VM_PERM_READ | ZX_VM_PERM_WRITE;
  res = zx::vmar::root_self()->map(flags, 0u, rb_vmo_, 0u, rb_sz_,
                                   reinterpret_cast<uintptr_t*>(&rb_virt_));

  if (res != ZX_OK) {
    printf("Failed to map ring buffer VMO (res %d)\n", res);
    return res;
  }

  // Success!  If this is an output device, zero out the buffer and we are done.
  if (!input()) {
    memset(rb_virt_, 0, rb_sz_);
  }

  return ZX_OK;
}

zx_status_t AudioDeviceStream::StartRingBuffer() {
  if (rb_ch_ == ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  auto result = audio_fidl::RingBuffer::Call::Start(zx::unowned_channel(rb_ch_));
  start_time_ = result->start_time;
  return result.status();
}

zx_status_t AudioDeviceStream::StopRingBuffer() {
  if (rb_ch_ == ZX_HANDLE_INVALID)
    return ZX_ERR_BAD_STATE;

  start_time_ = 0;
  auto result = audio_fidl::RingBuffer::Call::Stop(zx::unowned_channel(rb_ch_));
  return result.status();
}

void AudioDeviceStream::ResetRingBuffer() {
  if (rb_virt_ != nullptr) {
    ZX_DEBUG_ASSERT(rb_sz_ != 0);
    zx::vmar::root_self()->unmap(reinterpret_cast<uintptr_t>(rb_virt_), rb_sz_);
  }
  rb_ch_.reset();
  rb_vmo_.reset();
  rb_sz_ = 0;
  rb_virt_ = nullptr;
}

void AudioDeviceStream::Close() {
  ResetRingBuffer();
  stream_ch_.reset();
}

bool AudioDeviceStream::IsChannelConnected(const zx::channel& ch) {
  if (!ch.is_valid())
    return false;

  zx_signals_t junk;
  return ch.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time(), &junk) != ZX_ERR_TIMED_OUT;
}

}  // namespace utils
}  // namespace audio
