// 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 "src/speech/tts/tts_service_impl.h"

#include <lib/async/default.h>
#include <lib/fit/defer.h>

#include "src/speech/tts/tts_speaker.h"
#include "third_party/flite/include/flite_fuchsia.h"

namespace tts {

TtsServiceImpl::TtsServiceImpl(std::unique_ptr<sys::ComponentContext> startup_context)
    : startup_context_(std::move(startup_context)) {
  FX_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();
  FX_DCHECK(dispatcher_);
}

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

zx_status_t TtsServiceImpl::Init() {
  int res = flite_init();
  if (res < 0) {
    FX_LOGS(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() {
  FX_DCHECK(active_speakers_.size() == 0);
  FX_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(std::string 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 {
    FX_LOGS(ERROR) << "Failed to start to speak (res " << res << ")";
    return;
  }

  cleanup.cancel();
}

void TtsServiceImpl::Client::OnSpeakComplete(const 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
