// Copyright (c) 2012 The Chromium OS 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 <iostream>
#include <base/basictypes.h>
#include <base/command_line.h>
#include <chromeos/dbus/dbus.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/glib/object.h>
#include <dbus/dbus-glib-lowlevel.h>

#include "base/logging.h"
#include "interface.h"

// Forcibly namespace the dbus-bindings generated server bindings instead of
// modifying the files afterward.
namespace speech_synthesis {  // NOLINT
namespace gobject {  // NOLINT
#include "bindings/server.h"
}  // namespace gobject
}  // namespace speech_Synthesis

namespace speech_synthesis {

SpeechSynthesizerService::SpeechSynthesizerService()
    : speech_synthesizer_(NULL),
      main_loop_(g_main_loop_new(NULL, FALSE)) {
}

SpeechSynthesizerService::~SpeechSynthesizerService() {
  if (speech_synthesizer_)
    g_object_unref(speech_synthesizer_);
  g_main_loop_unref(main_loop_);
}

bool SpeechSynthesizerService::Initialize() {
  // Install the type-info for the service with dbus.
  dbus_g_object_type_install_info(
      gobject::speech_synthesizer_get_type(),
      &gobject::dbus_glib_speech_synthesizer_object_info);
  return Reset();
}

bool SpeechSynthesizerService::Reset() {
  if (speech_synthesizer_)
    g_object_unref(speech_synthesizer_);
  speech_synthesizer_ = reinterpret_cast<gobject::SpeechSynthesizer*>(
      g_object_new(gobject::speech_synthesizer_get_type(), NULL));

  // Allow references to this instance.
  speech_synthesizer_->service = this;

  if (main_loop_) {
    ::g_main_loop_unref(main_loop_);
  }
  main_loop_ = g_main_loop_new(NULL, false);
  if (!main_loop_) {
    LOG(ERROR) << "Failed to create main loop";
    return false;
  }
  return true;
}

// A utility function to send a signal to the browser.
void SendSignal(const char* signal_name) {
  chromeos::dbus::Proxy proxy(chromeos::dbus::GetSystemBusConnection(),
                              "/",
                              chromium::kChromiumInterface);
  DBusMessage* signal = ::dbus_message_new_signal(
      "/",
      chromium::kChromiumInterface,
      signal_name);
  DCHECK(signal);
  ::dbus_g_proxy_send(proxy.gproxy(), signal, NULL);
  ::dbus_message_unref(signal);
}

bool SpeechSynthesizerService::Run() {
  if (!main_loop_) {
    LOG(ERROR) << "You must have a main loop to call Run.";
    return false;
  }

  LOG(INFO) << "Running speech_synthesizer main_loop.";
  scoped_ptr<AudioOutput> audio_output(AudioOutput::Create());
  scoped_ptr<TtsEngine> engine(new PicoTtsEngine("/usr/share/tts/pico/"));
  ttsService_.reset(new TtsService(engine.get(), audio_output.get()));
  utterance_options_.reset(new UtteranceOptions());

  // Polling for idle shutdown.
  const int kTimeoutInterval = 10000;  // milliseconds
  UpdateLastCallTime();
  g_timeout_add(kTimeoutInterval, OnTimeout, this);

  if (ttsService_->StartService()) {
    SendSignal(chromium::kTTSReadySignal);
    g_main_loop_run(main_loop_);
  } else {
    SendSignal(chromium::kTTSFailedSignal);
    return false;
  }
  ttsService_->StopService();
  return true;
}

gboolean SpeechSynthesizerService::AddProperties(gchar *properties) {
  if (properties == NULL) {
    return false;
  }
  string props(properties);
  if (props.compare("") == 0) {
    return true;
  }
  string token = "";
  while(1) {
    unsigned int sep = props.find(";");
    if (sep == string::npos) {
      token = props;
    } else {
      token = props.substr(0, sep);
      props = props.substr(sep + 1);
    }
    if (token.empty() || token.compare("") == 0) {
      break;
    }
    int eq = token.find("=");
    string key = token.substr(0, eq);
    string value = token.substr(eq + 1);

    if (key.compare("rate") == 0) {
      utterance_options_->rate = atof(value.c_str());
    } else if (key.compare("pitch") == 0) {
      utterance_options_->pitch = atof(value.c_str());
    } else if (key.compare("volume") == 0) {
      utterance_options_->volume = atof(value.c_str());
    } else if (key.compare("name") == 0) {
      utterance_options_->voice_options.name = value;
    } else if (key.compare("language") == 0) {
      utterance_options_->voice_options.language = value;
    } else if (key.compare("sample_rate") == 0) {
      utterance_options_->voice_options.sample_rate = atoi(value.c_str());
    } else if (key.compare("quality") == 0) {
      utterance_options_->voice_options.quality =
          (tts_quality) atoi(value.c_str());
    } else if (key.compare("region") == 0) {
      utterance_options_->voice_options.region = value;
    } else if (key.compare("gender") == 0) {
      utterance_options_->voice_options.gender =
          (tts_gender) atoi(value.c_str());
    } else if (key.compare("age") == 0) {
      utterance_options_->voice_options.age = atoi(value.c_str());
    } else if (key.compare("enqueue") == 0) {
      utterance_options_->enqueue = atoi(value.c_str()) == 1;
    } else if (key.compare("interruptible") == 0) {
      utterance_options_->interruptible = atoi(value.c_str()) == 1;
    }
    if (sep == string::npos) {
      break;
    }
  }
  return true;
}

void SpeechSynthesizerService::UpdateLastCallTime() {
  time_last_call_ = base::Time::Now();
}

void SpeechSynthesizerService::ShutdownIfIdle() {
  const int kShutdownTimeout = 60000;
  const base::Time shutdown_time =
      time_last_call_ + base::TimeDelta::FromMilliseconds(kShutdownTimeout);
  if (base::Time::Now() >= shutdown_time &&
      ttsService_->GetStatus() == TTS_IDLE)
    g_main_loop_quit(main_loop());
}

// static
gboolean SpeechSynthesizerService::OnTimeout(gpointer user_data) {
  static_cast<SpeechSynthesizerService*>(user_data)->ShutdownIfIdle();
  // TRUE means this method will be called again, repeatedly.
  return TRUE;
}

///////////////////////////////////////////////////////////////////////////////
// SpeechSynthesizerService commands

gboolean SpeechSynthesizerService::Speak(gchar *text,
                                         gchar *properties,
                                         GError **error) {
  UpdateLastCallTime();
  AddProperties(properties);
  ttsService_->Speak(text, *utterance_options_);
  utterance_options_->enqueue = false;
  utterance_options_->interruptible = true;
  return true;
}

gboolean SpeechSynthesizerService::Stop(GError **error) {
  UpdateLastCallTime();
  ttsService_->Stop();
  return true;
}

gboolean SpeechSynthesizerService::IsSpeaking(
    gboolean* OUT_isSpeaking_requested,
    GError **error) {
  UpdateLastCallTime();
  *OUT_isSpeaking_requested = (ttsService_->GetStatus() == TTS_BUSY);
  return true;
}

gboolean SpeechSynthesizerService::Shutdown(GError **error) {
  g_main_loop_quit(main_loop());
  return true;
}

} // namespace speech_synthesis
