// 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/fit/defer.h>

#include "garnet/bin/tts/tts_service_impl.h"
#include "garnet/bin/tts/tts_speaker.h"
#include "third_party/flite/include/flite_fuchsia.h"

namespace tts {

TtsServiceImpl::TtsServiceImpl(
    std::unique_ptr<component::StartupContext> startup_context)
    : startup_context_(std::move(startup_context)) {
  FXL_DCHECK(startup_context_);

  startup_context_->outgoing().AddPublicService<fuchsia::tts::TtsService>(
      [this](fidl::InterfaceRequest<fuchsia::tts::TtsService> request) {
        clients_.insert(new Client(this, std::move(request)));
      });

  // Stash a pointer to our async_t.
  dispatcher_ = async_get_default_dispatcher();
  FXL_DCHECK(dispatcher_);
}

TtsServiceImpl::~TtsServiceImpl() { FXL_DCHECK(clients_.size() == 0); }

zx_status_t TtsServiceImpl::Init() {
  int res = flite_init();
  if (res < 0) {
    FXL_LOG(ERROR) << "Failed to initialize flite (res " << res << ")";
    return ZX_ERR_INTERNAL;
  }

  return ZX_OK;
}

TtsServiceImpl::Client::Client(TtsServiceImpl* owner,
                               fidl::InterfaceRequest<TtsService> request)
    : owner_(owner), binding_(this, std::move(request)) {
  binding_.set_error_handler([this](zx_status_t status) { Shutdown(); });
}

TtsServiceImpl::Client::~Client() {
  FXL_DCHECK(active_speakers_.size() == 0);
  FXL_DCHECK(binding_.is_bound() == false);
}

void TtsServiceImpl::Client::Shutdown() {
  for (const auto& speaker : active_speakers_) {
    speaker->Shutdown();
  }

  binding_.Unbind();
  active_speakers_.clear();
  owner_->clients_.erase(owner_->clients_.find(this));
}

void TtsServiceImpl::Client::Say(fidl::StringPtr words, uint64_t token,
                                 SayCallback cbk) {
  auto cleanup = fit::defer([this] { Shutdown(); });
  auto speaker = std::make_shared<TtsSpeaker>(owner_->dispatcher_);

  if (speaker->Init(owner_->startup_context_) != ZX_OK) {
    return;
  }

  fit::closure on_speak_complete = [this, speaker, token,
                                    say_callback = std::move(cbk)]() mutable {
    OnSpeakComplete(std::move(speaker), token, std::move(say_callback));
  };

  zx_status_t res =
      speaker->Speak(std::move(words), std::move(on_speak_complete));
  if (res == ZX_OK) {
    active_speakers_.insert(std::move(speaker));
  } else {
    FXL_LOG(ERROR) << "Failed to start to speak (res " << res << ")";
    return;
  }

  cleanup.cancel();
}

void TtsServiceImpl::Client::OnSpeakComplete(
    std::shared_ptr<TtsSpeaker> speaker, uint64_t token, SayCallback cbk) {
  auto iter = active_speakers_.find(speaker);

  if (iter == active_speakers_.end()) {
    return;
  }

  speaker->Shutdown();
  active_speakers_.erase(iter);
  cbk(token);
}

}  // namespace tts
