// 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 "garnet/examples/mediaplayer/audio_player/audio_player.h"

#include <iomanip>

#include <fcntl.h>
#include <fuchsia/media/cpp/fidl.h>
#include <lib/async-loop/loop.h>
#include <lib/async/default.h>
#include <lib/fit/function.h>

#include "garnet/examples/mediaplayer/audio_player/audio_player_params.h"
#include "lib/component/cpp/connect.h"
#include "lib/fidl/cpp/optional.h"
#include "lib/fsl/io/fd.h"
#include "lib/fxl/logging.h"
#include "lib/media/timeline/timeline.h"
#include "lib/url/gurl.h"

namespace examples {

AudioPlayer::AudioPlayer(const AudioPlayerParams& params,
                         fit::closure quit_callback)
    : quit_callback_(std::move(quit_callback)),
      quit_when_done_(!params.stay()) {
  FXL_DCHECK(params.is_valid());
  FXL_DCHECK(quit_callback_);

  auto startup_context = component::StartupContext::CreateFromStartupInfo();

  player_ = startup_context
                ->ConnectToEnvironmentService<fuchsia::mediaplayer::Player>();
  player_.events().OnStatusChanged =
      [this](fuchsia::mediaplayer::PlayerStatus status) {
        HandleStatusChanged(status);
      };

  if (!params.url().empty()) {
    url::GURL url = url::GURL(params.url());

    if (url.SchemeIsFile()) {
      player_->SetFileSource(fsl::CloneChannelFromFileDescriptor(
          fxl::UniqueFD(open(url.path().c_str(), O_RDONLY)).get()));
    } else {
      player_->SetHttpSource(params.url(), nullptr);
    }
    GetKeystroke();

    player_->Play();
  }
}

AudioPlayer::~AudioPlayer() {}

void AudioPlayer::HandleStatusChanged(
    const fuchsia::mediaplayer::PlayerStatus& status) {
  // Process status received from the player.
  if (status.end_of_stream && quit_when_done_) {
    quit_callback_();
    FXL_LOG(INFO) << "Reached end-of-stream. Quitting.";
  }

  if (status.problem) {
    if (!problem_shown_) {
      FXL_DLOG(INFO) << "PROBLEM: " << status.problem->type << ", "
                     << status.problem->details;
      problem_shown_ = true;
      if (quit_when_done_) {
        quit_callback_();
        FXL_LOG(INFO) << "Problem detected. Quitting.";
      }
    }
  } else {
    problem_shown_ = false;
  }

  if (status.metadata && !metadata_shown_) {
    FXL_LOG(INFO) << "duration   " << std::fixed << std::setprecision(1)
                  << double(status.duration_ns) / 1000000000.0 << " seconds";
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_TITLE,
                             "title      ");
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_ARTIST,
                             "artist     ");
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_ALBUM,
                             "album      ");
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_PUBLISHER,
                             "publisher  ");
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_GENRE,
                             "genre      ");
    MaybeLogMetadataProperty(*status.metadata,
                             fuchsia::mediaplayer::METADATA_LABEL_COMPOSER,
                             "composer   ");
    metadata_shown_ = true;
  }
}

void AudioPlayer::HandleKeystroke(zx_status_t status, uint32_t events) {
  if (status != ZX_OK) {
    printf("Bad status in HandleKeystroke (status %d)\n", status);
    quit_callback_();
  }

  char c;
  ssize_t res = ::read(STDIN_FILENO, &c, sizeof(c));
  if (res != 1) {
    printf("Error reading keystroke (res %zd, errno %d)\n", res, errno);
    quit_callback_();
  }

  switch (c) {
    case 'q':
    case 'Q':
      quit_callback_();
      break;
    default:
      printf("q - Quit\n");
      break;
  }

  GetKeystroke();
}

void AudioPlayer::GetKeystroke() {
  keystroke_waiter_.Wait(
      [this](zx_status_t s, uint32_t e) { HandleKeystroke(s, e); },
      STDIN_FILENO, POLLIN);
}

void AudioPlayer::MaybeLogMetadataProperty(
    const fuchsia::mediaplayer::Metadata& metadata,
    const std::string& property_label, const std::string& prefix) {
  for (auto& property : metadata.properties) {
    if (property.label == property_label) {
      FXL_LOG(INFO) << prefix << property.value;
      return;
    }
  }
}

}  // namespace examples
