// Copyright 2016 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 "topaz/examples/media/vu_meter/vu_meter_view.h"

#include <hid/usages.h>

#include <iomanip>

#include "lib/component/cpp/connect.h"
#include "lib/fxl/logging.h"
#include "lib/media/audio/types.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkPath.h"

constexpr zx_duration_t kCaptureDuration = ZX_MSEC(20);
constexpr uint64_t kBytesPerFrame = 4;

namespace examples {

VuMeterView::VuMeterView(scenic::ViewContext view_context, async::Loop* loop)
    : SkiaView(std::move(view_context), "VU Meter"),
      loop_(loop),
      fast_left_(kFastDecay),
      fast_right_(kFastDecay),
      slow_left_(kSlowDecay),
      slow_right_(kSlowDecay) {
  FXL_DCHECK(loop);

  auto audio =
      startup_context()->ConnectToEnvironmentService<fuchsia::media::Audio>();
  audio->CreateAudioCapturer(audio_capturer_.NewRequest(), false);

  audio_capturer_.set_error_handler([this](zx_status_t status) {
    FXL_LOG(ERROR) << "Connection error occurred. Quitting.";
    Shutdown();
  });

  audio_capturer_->GetStreamType([this](fuchsia::media::StreamType type) {
    OnDefaultFormatFetched(std::move(type));
  });
}

bool VuMeterView::OnInputEvent(fuchsia::ui::input::InputEvent event) {
  bool handled = false;
  if (event.is_pointer()) {
    auto& pointer = event.pointer();
    if (pointer.phase == fuchsia::ui::input::PointerEventPhase::DOWN) {
      ToggleStartStop();
      handled = true;
    }
  } else if (event.is_keyboard()) {
    auto& keyboard = event.keyboard();
    if (keyboard.phase == fuchsia::ui::input::KeyboardEventPhase::PRESSED) {
      switch (keyboard.hid_usage) {
        case HID_USAGE_KEY_SPACE:
          ToggleStartStop();
          handled = true;
          break;
        case HID_USAGE_KEY_Q:
          Shutdown();
          handled = true;
          break;
        default:
          break;
      }
    }
  }
  return handled;
}

void VuMeterView::OnSceneInvalidated(
    fuchsia::images::PresentationInfo presentation_info) {
  SkCanvas* canvas = AcquireCanvas();
  if (canvas) {
    DrawContent(canvas);
    ReleaseAndSwapCanvas();
  }
}

void VuMeterView::DrawContent(SkCanvas* canvas) {
  canvas->clear(SK_ColorBLACK);

  SkPaint paint;
  paint.setFlags(SkPaint::kAntiAlias_Flag);

  paint.setColor(SK_ColorCYAN);
  canvas->drawCircle(
      logical_size().width / 3.0f, logical_size().height / 2,
      (fast_left_.current() * logical_size().width / 2) / kVuFullWidth, paint);
  canvas->drawCircle(
      2.0f * logical_size().width / 3.0f, logical_size().height / 2,
      (fast_right_.current() * logical_size().width / 2) / kVuFullWidth, paint);

  paint.setColor(SK_ColorWHITE);
  paint.setStyle(SkPaint::kStroke_Style);
  paint.setStrokeWidth(SkIntToScalar(3));
  canvas->drawCircle(
      logical_size().width / 3.0f, logical_size().height / 2,
      (slow_left_.current() * logical_size().width / 2) / kVuFullWidth, paint);
  canvas->drawCircle(
      2.0f * logical_size().width / 3.0f, logical_size().height / 2,
      (slow_right_.current() * logical_size().width / 2) / kVuFullWidth, paint);
}

void VuMeterView::SendCaptureRequest() {
  if (!started_ || request_in_flight_) {
    return;
  }

  // clang-format off
  audio_capturer_->CaptureAt(
      0, 0, payload_buffer_.size() / kBytesPerFrame,
      [this](fuchsia::media::StreamPacket packet) {
        OnPacketCaptured(std::move(packet));
      });
  // clang-format on

  request_in_flight_ = true;
}

void VuMeterView::OnDefaultFormatFetched(
    fuchsia::media::StreamType default_type) {
  // Set the media type, keep the default sample rate but make sure that we
  // normalize to stereo 16-bit LPCM.
  FXL_DCHECK(default_type.medium_specific.is_audio());
  const auto& audio_details = default_type.medium_specific.audio();

  audio_capturer_->SetPcmStreamType(
      media::CreateAudioStreamType(fuchsia::media::AudioSampleFormat::SIGNED_16,
                                   2, audio_details.frames_per_second));

  uint64_t payload_buffer_size =
      kBytesPerFrame *
      ((kCaptureDuration * audio_details.frames_per_second) / ZX_SEC(1));

  constexpr zx_rights_t rights =
      ZX_RIGHT_TRANSFER | ZX_RIGHT_READ | ZX_RIGHT_WRITE | ZX_RIGHT_MAP;
  zx_status_t zx_res;
  zx::vmo vmo;
  zx_res = payload_buffer_.CreateAndMap(payload_buffer_size, ZX_VM_PERM_READ,
                                        nullptr, &vmo, rights);
  if (zx_res != ZX_OK) {
    FXL_LOG(ERROR) << "Failed to create payload buffer (res " << zx_res << ")";
    Shutdown();
    return;
  }

  audio_capturer_->AddPayloadBuffer(0, std::move(vmo));

  // Start capturing.
  ToggleStartStop();
}

void VuMeterView::OnPacketCaptured(fuchsia::media::StreamPacket packet) {
  request_in_flight_ = false;
  if (!started_) {
    return;
  }

  // TODO(dalesat): Synchronize display and captured audio.
  uint32_t frame_count =
      static_cast<uint32_t>(payload_buffer_.size() / kBytesPerFrame);
  int16_t* samples = reinterpret_cast<int16_t*>(payload_buffer_.start());

  for (uint32_t i = 0; i < frame_count; ++i) {
    int16_t abs_sample = std::abs(samples[0]);
    fast_left_.Process(abs_sample);
    slow_left_.Process(abs_sample);

    abs_sample = std::abs(samples[1]);
    fast_right_.Process(abs_sample);
    slow_right_.Process(abs_sample);

    samples += 2;
  }

  InvalidateScene();
  SendCaptureRequest();
}

void VuMeterView::Shutdown() {
  audio_capturer_.Unbind();
  loop_->Quit();
}

}  // namespace examples
