/**
* Copyright 2020 Comcast Cable Communications Management, LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "Module.h"
#include <interfaces/IMemory.h>
#include <interfaces/IBrowser.h>
#include <interfaces/IDictionary.h>
#if defined(PLUGIN_COBALT_ENABLE_FOCUS_IFACE) && PLUGIN_COBALT_ENABLE_FOCUS_IFACE
#include <interfaces/IFocus.h>
#endif

extern "C" {

int  StarboardMain(int argc, char **argv);
void SbRdkHandleDeepLink(const char* link);
void SbRdkSuspend();
void SbRdkResume();
void SbRdkPause();
void SbRdkUnpause();
void SbRdkQuit();
void SbRdkSetSetting(const char* key, const char* json);
int  SbRdkGetSetting(const char* key, char** out_json);

typedef int (*SbRdkCallbackFunc)(void *user_data);
void SbRdkSetConcealRequestHandler(SbRdkCallbackFunc cb, void* user_data);
void SbRdkSetCobaltExitStrategy(const char* strategy);

}  // extern "C"

namespace WPEFramework {

namespace Plugin {

static constexpr char kDefaultContentDir[] =
  "/usr/share/content/data:"
  "/media/apps/libcobalt/usr/share/content/data:"
  "/tmp/libcobalt/usr/share/content/data";

static void SetThunderAccessPointIfNeeded() {
  const std::string envName = _T("THUNDER_ACCESS");
  std::string envVal;
  if (Core::SystemInfo::GetEnvironment(envName, envVal))
    return;

  Core::File file("/etc/WPEFramework/config.json", false);
  if (!file.Open(true))
    return;

  Core::JSON::DecUInt16 port;
  Core::JSON::String binding;
  Core::JSON::Container config;
  config.Add("port", &port);
  config.Add("binding", &binding);
  if (config.IElement::FromFile(file)) {
    envVal = binding.Value() + ":" + std::to_string(port.Value());
    Core::SystemInfo::SetEnvironment("THUNDER_ACCESS", envVal);
  }
  file.Close();
}

enum StateChangeCommand : uint16_t {
  SUSPEND = PluginHost::IStateControl::SUSPEND,
  RESUME = PluginHost::IStateControl::RESUME,
  BACKGROUND
};

class CobaltImplementation:
    public Exchange::IBrowser,
    public PluginHost::IStateControl,
    public Exchange::IDictionary
#if defined(PLUGIN_COBALT_ENABLE_FOCUS_IFACE) && PLUGIN_COBALT_ENABLE_FOCUS_IFACE
    , public Exchange::IFocus
#endif
{
private:
  class Config: public Core::JSON::Container {
  private:
    Config(const Config&);
    Config& operator=(const Config&);
  public:
    Config()
      : Core::JSON::Container()
      , Url()
      , ClientIdentifier()
      , Language()
      , ContentDir()
      , PreloadEnabled()
      , EssosContextDestroy()
      , AutoSuspendDelay() {
      Add(_T("url"), &Url);
      Add(_T("clientidentifier"), &ClientIdentifier);
      Add(_T("language"), &Language);
      Add(_T("contentdir"), &ContentDir);
      Add(_T("gstdebug"), &GstDebug);
      Add(_T("essoscontextdestroy"), &EssosContextDestroy);
      Add(_T("preload"), &PreloadEnabled);
      Add(_T("autosuspenddelay"), &AutoSuspendDelay);
      Add(_T("systemproperties"), &SystemProperties);
      Add(_T("closurepolicy"), &ClosurePolicy);
      Add(_T("fireboltendpoint"), &FireboltEndpoint);
    }
    ~Config() {
    }

  public:
    Core::JSON::String Url;
    Core::JSON::String ClientIdentifier;
    Core::JSON::String Language;
    Core::JSON::String ContentDir;
    Core::JSON::String GstDebug;
    Core::JSON::String EssosContextDestroy;
    Core::JSON::Boolean PreloadEnabled;
    Core::JSON::DecUInt16 AutoSuspendDelay;
    Core::JSON::VariantContainer SystemProperties;
    Core::JSON::String ClosurePolicy;
    Core::JSON::String FireboltEndpoint;
  };

  class NotificationSink: public Core::Thread {
  private:
    NotificationSink() = delete;
    NotificationSink(const NotificationSink&) = delete;
    NotificationSink& operator=(const NotificationSink&) = delete;

  public:
    NotificationSink(CobaltImplementation &parent) :
      _parent(parent), _command(
        StateChangeCommand::SUSPEND) {
    }
    virtual ~NotificationSink() {
      Stop();
      Wait(Thread::STOPPED | Thread::BLOCKED, Core::infinite);
    }

  public:
    void RequestForStateChange(
      const StateChangeCommand command) {
      _lock.Lock();
      _command = command;
      _lock.Unlock();
      Run();
    }

  private:
    virtual uint32_t Worker() {
      bool success = false;

      _lock.Lock();
      const StateChangeCommand command = _command;
      _lock.Unlock();

      if ((IsRunning() == true) && (success == false)) {
        success = _parent.RequestForStateChange(command);
      }
      Block();
      _parent.StateChangeCompleted(success, command);

      if (success == true) {
        _lock.Lock();
        bool completed = (command == _command);
        _lock.Unlock();
        // Spin one more time
        if (!completed)
          Run();
      }

      return (Core::infinite);
    }

  private:
    CobaltImplementation &_parent;
    StateChangeCommand _command;
    mutable Core::CriticalSection _lock;
  };

  class DelayedSuspend
  {
  private:
    DelayedSuspend() = delete;
    DelayedSuspend(const DelayedSuspend&) = delete;
    DelayedSuspend& operator=(const DelayedSuspend&) = delete;

  private:
    bool _scheduled;
    CobaltImplementation &_parent;

    friend Core::ThreadPool::JobType<DelayedSuspend&>;
    Core::WorkerPool::JobType<DelayedSuspend&> _worker;

    void Dispatch()
    {
      _parent.RequestDelayedSuspend();
      _scheduled = false;
    }

  public:
    DelayedSuspend(CobaltImplementation &parent)
      : _scheduled(false)
      , _parent(parent)
      , _worker(*this)
    {
    }

    bool IsScheduled() const
    {
      return _scheduled;
    }

    void Schedule(const Core::Time& time)
    {
      _scheduled = _worker.Schedule(time);
    }

    void Cancel()
    {
      _worker.Revoke();
      _scheduled = false;
    }
  };

  class CobaltWindow : public Core::Thread {
  private:
    CobaltWindow(const CobaltWindow&) = delete;
    CobaltWindow& operator=(const CobaltWindow&) = delete;

  public:
    CobaltWindow(CobaltImplementation& parent)
      : Core::Thread(0, _T("Cobalt"))
      , _url("https://www.youtube.com/tv")
      , _parent(parent)
    {
    }
    virtual ~CobaltWindow()
    {
      Block();
      SbRdkQuit();
      Wait(Thread::BLOCKED | Thread::STOPPED | Thread::STOPPING, Core::infinite);
    }

    uint32_t Configure(PluginHost::IShell* service) {
      if (IsRunning() == true)
        return Core::ERROR_ILLEGAL_STATE;

      uint32_t result = Core::ERROR_NONE;

      string config_line = service->ConfigLine();
      SYSLOG(Logging::Notification, (_T("Cobalt config line: --- %s ---\n"), config_line.c_str()));

      Config config;
      config.FromString(config_line);

      Core::Directory(service->PersistentPath().c_str()).CreatePath();
      Core::SystemInfo::SetEnvironment(_T("HOME"), service->PersistentPath());
      Core::SystemInfo::SetEnvironment(_T("COBALT_TEMP"), service->VolatilePath());
      if (config.ClientIdentifier.IsSet() == true) {
        string value(service->Callsign() + ',' + config.ClientIdentifier.Value());
        Core::SystemInfo::SetEnvironment(_T("CLIENT_IDENTIFIER"), value);
        Core::SystemInfo::SetEnvironment(_T("WAYLAND_DISPLAY"), config.ClientIdentifier.Value());
      } else {
        Core::SystemInfo::SetEnvironment(_T("CLIENT_IDENTIFIER"), service->Callsign());
      }

      SetThunderAccessPointIfNeeded();

      if (config.Url.IsSet() == true) {
        _url = config.Url.Value();
      }

      if (config.Language.IsSet() == true) {
        string lang = config.Language.Value();
        Core::SystemInfo::SetEnvironment(_T("LANG"), lang);
      }

      if (config.ContentDir.IsSet() == true) {
        string contentdir = config.ContentDir.Value();
        Core::SystemInfo::SetEnvironment(_T("COBALT_CONTENT_DIR"), contentdir);
      } else {
        Core::SystemInfo::SetEnvironment(_T("COBALT_CONTENT_DIR"), kDefaultContentDir);
      }

      {
        string envVal, gstDebug = "gstplayer:4,2";
        if (Core::SystemInfo::GetEnvironment(_T("GST_DEBUG"), envVal) && !envVal.empty())
          gstDebug = "," + envVal;
        if (config.GstDebug.IsSet() == true)
          gstDebug += "," + config.GstDebug.Value();
        Core::SystemInfo::SetEnvironment(_T("GST_DEBUG"), gstDebug);
      }

      if (config.EssosContextDestroy.IsSet() == true) {
        string val = config.EssosContextDestroy.Value();
        Core::SystemInfo::SetEnvironment(_T("COBALT_ESSOS_CONTEXT_DESTROY"), val);
      }

      if (config.PreloadEnabled.IsSet() == true) {
        _preloadEnabled = config.PreloadEnabled.Value();
      }

      if (config.AutoSuspendDelay.IsSet() == true) {
        _autoSuspendDelayInSeconds = config.AutoSuspendDelay.Value();
      }

      if (config.SystemProperties.IsSet() == true) {
        std::string properties;
        if (config.SystemProperties.ToString(properties))
          SbRdkSetSetting("systemproperties", properties.c_str());
      }

      if (config.FireboltEndpoint.IsSet() == true)
        Core::SystemInfo::SetEnvironment(_T("FIREBOLT_ENDPOINT"), config.FireboltEndpoint.Value());

      SYSLOG(Logging::Notification, (_T("Preload is set to: %s\n"), _preloadEnabled ? "true" : "false"));

      if (config.ClosurePolicy.IsSet() == true) {
#if defined(PLUGIN_COBALT_ENABLE_CLOSUREPOLICY) && PLUGIN_COBALT_ENABLE_CLOSUREPOLICY
        SbRdkSetCobaltExitStrategy(config.ClosurePolicy.Value().data());
#else
        SYSLOG(Logging::Notification, (_T("Ignore 'closurepolicy' configuration, support is disabled\n")));
#endif
      }

      SbRdkSetConcealRequestHandler([](void* data)-> int {
        CobaltWindow* window = reinterpret_cast<CobaltWindow*>(data);
        window->_parent.OnConcealRequest();
        return 0;
      }, this);

      Run();
      return result;
    }

    bool Suspend(const bool suspend)
    {
      if (suspend == true) {
        SbRdkSuspend();
      }
      else {
        SbRdkResume();
      }
      return (true);
    }

    bool Pause(const bool paused)
    {
      if (paused == true) {
        SbRdkPause();
      }
      else {
        SbRdkUnpause();
      }
      return (true);
    }

    string Url() const { return _url; }

    bool IsPreloadEnabled() const { return _preloadEnabled; }

    uint16_t AutoSuspendDelayInSeconds() const { return _autoSuspendDelayInSeconds; }

  private:
    bool Initialize() override
    {
      sigset_t mask;
      sigemptyset(&mask);
      sigaddset(&mask, SIGQUIT);
      sigaddset(&mask, SIGUSR1);
      sigaddset(&mask, SIGCONT);
      pthread_sigmask(SIG_UNBLOCK, &mask, nullptr);
      return (true);
    }
    uint32_t Worker() override
    {
      const std::string cmdURL = "--url=" + _url;
      std::vector<const char*> argv;

      argv.push_back("Cobalt");

      if (!_url.empty())
        argv.push_back(cmdURL.c_str());
      if (IsPreloadEnabled())
        argv.push_back("--preload");

#ifdef ENABLE_EVERGREEN_LITE
      argv.push_back("--evergreen_lite");
#endif

      {
        std::string args_str;
        for (const char* arg: argv) {
          if (!args_str.empty())
            args_str += " ";
          args_str += arg;
        }
        SYSLOG(Logging::Notification, (_T("StarboardMain args: %s\n"), args_str.c_str()));
      }

      if (IsRunning() == true)
          _exitCode = StarboardMain(argv.size(), const_cast<char**>(argv.data()));
      if (IsRunning() == true) // app initiated exit
          _parent.StateChange(PluginHost::IStateControl::EXITED);
      Block();
      return (Core::infinite);
    }

    int _exitCode { 0 };
    string _url;
    CobaltImplementation &_parent;
    bool _preloadEnabled { false };
    uint16_t _autoSuspendDelayInSeconds { 30 };
  };

private:
  CobaltImplementation(const CobaltImplementation&) = delete;
  CobaltImplementation& operator=(const CobaltImplementation&) = delete;

public:
  CobaltImplementation() :
    _window(*this),
    _adminLock(),
    _state(PluginHost::IStateControl::UNINITIALIZED),
    _statePending(PluginHost::IStateControl::UNINITIALIZED),
    _cobaltClients(),
    _stateControlClients(),
    _sink(*this),
    _delayedSuspend(*this) {
  }

  virtual ~CobaltImplementation() {
  }

  virtual uint32_t Configure(PluginHost::IShell *service) {
    uint32_t result = _window.Configure(service);
    if (_window.IsPreloadEnabled()) {
      _state = PluginHost::IStateControl::SUSPENDED;
      _statePending = PluginHost::IStateControl::SUSPENDED;
      _delayedSuspend.Schedule(Core::Time::Now().Add(_window.AutoSuspendDelayInSeconds() * 1000));
    } else {
      _state = PluginHost::IStateControl::RESUMED;
    }
    return (result);
  }

  virtual void SetURL(const string &URL) override {
    SYSLOG(Logging::Notification, (_T("deeplink=%s\n"), URL.c_str()));
    SbRdkHandleDeepLink(URL.c_str());
  }

  virtual string GetURL() const override {
    return _window.Url();
  }

  virtual uint32_t GetFPS() const override {
    return 0;
  }

  virtual void Hide(const bool hidden) {
  }

  virtual void Register(Exchange::IBrowser::INotification *sink) {
    _adminLock.Lock();

    // Make sure a sink is not registered multiple times.
    ASSERT(
      std::find(_cobaltClients.begin(), _cobaltClients.end(), sink)
      == _cobaltClients.end());

    _cobaltClients.push_back(sink);
    sink->AddRef();

    _adminLock.Unlock();
  }

  virtual void Unregister(Exchange::IBrowser::INotification *sink) {
    _adminLock.Lock();

    std::list<Exchange::IBrowser::INotification*>::iterator index(
      std::find(_cobaltClients.begin(), _cobaltClients.end(), sink));

    // Make sure you do not unregister something you did not register !!!
    ASSERT(index != _cobaltClients.end());

    if (index != _cobaltClients.end()) {
      (*index)->Release();
      _cobaltClients.erase(index);
    }

    _adminLock.Unlock();
  }

  virtual void Register(PluginHost::IStateControl::INotification *sink) {
    _adminLock.Lock();

    // Make sure a sink is not registered multiple times.
    ASSERT(
      std::find(_stateControlClients.begin(),
                _stateControlClients.end(), sink)
      == _stateControlClients.end());

    _stateControlClients.push_back(sink);
    sink->AddRef();

    _adminLock.Unlock();
  }

  virtual void Unregister(PluginHost::IStateControl::INotification *sink) {
    _adminLock.Lock();

    std::list<PluginHost::IStateControl::INotification*>::iterator index(
      std::find(_stateControlClients.begin(),
                _stateControlClients.end(), sink));

    // Make sure you do not unregister something you did not register !!!
    ASSERT(index != _stateControlClients.end());

    if (index != _stateControlClients.end()) {
      (*index)->Release();
      _stateControlClients.erase(index);
    }

    _adminLock.Unlock();
  }

  virtual PluginHost::IStateControl::state State() const {
    return (_state);
  }

  virtual uint32_t Request(const PluginHost::IStateControl::command command) {
    uint32_t result = Core::ERROR_ILLEGAL_STATE;

    _adminLock.Lock();

    if (_state == PluginHost::IStateControl::UNINITIALIZED || _state == PluginHost::IStateControl::EXITED) {
      ASSERT(false);
    } else {
      switch (command) {
        case PluginHost::IStateControl::SUSPEND:
          if (_state == PluginHost::IStateControl::RESUMED || _statePending == PluginHost::IStateControl::RESUMED) {
            _statePending = PluginHost::IStateControl::SUSPENDED;
            _sink.RequestForStateChange(
              StateChangeCommand::SUSPEND);
          }
          result = Core::ERROR_NONE;
          break;
        case PluginHost::IStateControl::RESUME:
          if (_state == PluginHost::IStateControl::SUSPENDED || _statePending == PluginHost::IStateControl::SUSPENDED) {
            _statePending = PluginHost::IStateControl::RESUMED;
            _sink.RequestForStateChange(
              StateChangeCommand::RESUME);
          }
          if (_delayedSuspend.IsScheduled()) {
            _delayedSuspend.Cancel();
          }
          result = Core::ERROR_NONE;
          break;
        default:
          break;
      }
    }

    _adminLock.Unlock();

    return result;
  }

  void StateChangeCompleted(bool success,
                            const StateChangeCommand request) {
    if (success) {
      switch (request) {
        case StateChangeCommand::RESUME:

          _adminLock.Lock();

          if (_state != PluginHost::IStateControl::RESUMED) {
            StateChange(PluginHost::IStateControl::RESUMED);
          }

          _adminLock.Unlock();
          break;
        case StateChangeCommand::SUSPEND:

          _adminLock.Lock();

          if (_state != PluginHost::IStateControl::SUSPENDED) {
            StateChange(PluginHost::IStateControl::SUSPENDED);
          }

          _adminLock.Unlock();
          break;
        case StateChangeCommand::BACKGROUND:
          break;
        default:
          ASSERT(false);
          break;
      }
    } else {
      StateChange(PluginHost::IStateControl::EXITED);
    }
  }

  void RequestDelayedSuspend() {
    _adminLock.Lock();
    if (_state == PluginHost::IStateControl::SUSPENDED && _statePending == PluginHost::IStateControl::SUSPENDED) {
      _sink.RequestForStateChange(StateChangeCommand::SUSPEND);
    }
    _adminLock.Unlock();
  }

#if defined(PLUGIN_COBALT_ENABLE_FOCUS_IFACE) && PLUGIN_COBALT_ENABLE_FOCUS_IFACE
  // IFocus
  uint32_t Focused(const bool focused) override {
    _adminLock.Lock();
    if (_state == PluginHost::IStateControl::RESUMED || _statePending == PluginHost::IStateControl::RESUMED) {
      if (focused)
        _sink.RequestForStateChange(StateChangeCommand::RESUME);
      else
        _sink.RequestForStateChange(StateChangeCommand::BACKGROUND);
    }
    _adminLock.Unlock();
    return Core::ERROR_NONE;
  };
#endif

  // IDictionary iface
  void Register(const string& nameSpace, struct IDictionary::INotification* sink) override  {  }
  void Unregister(const string& nameSpace, struct IDictionary::INotification* sink) override  {  }
  IIterator* Get(const string& nameSpace) const override { return nullptr; }
  bool Get(const string& nameSpace, const string& key, string& value /* @out */) const override {
    if (nameSpace == "settings") {
      if (key == "accessibility") {
        char* json = nullptr;
        if (SbRdkGetSetting(key.c_str(), &json) == 0) {
          value.assign(json);
          free(json);
          return true;
        }
      }
    }
    return false;
  }
  bool Set(const string& nameSpace, const string& key, const string& value) override {
    if (nameSpace == "settings") {
      if (key == "accessibility") {
        SbRdkSetSetting(key.c_str(), value.c_str());
        return true;
      }
    }
    return false;
  }

  void OnConcealRequest() {
    // Device lifecycle tests from YTS expect 'suspend' behavior on 'conceal'
    Request(PluginHost::IStateControl::SUSPEND);
    NotifyClosure();
  }

  BEGIN_INTERFACE_MAP (CobaltImplementation)
  INTERFACE_ENTRY (Exchange::IBrowser)
  INTERFACE_ENTRY (PluginHost::IStateControl)
  INTERFACE_ENTRY (Exchange::IDictionary)
#if defined(PLUGIN_COBALT_ENABLE_FOCUS_IFACE) && PLUGIN_COBALT_ENABLE_FOCUS_IFACE
  INTERFACE_ENTRY (Exchange::IFocus)
#endif
  END_INTERFACE_MAP

private:
  static const char* ToString(const StateChangeCommand command) {
    switch(command) {
      case StateChangeCommand::SUSPEND:
        return "suspend";
      case StateChangeCommand::RESUME:
        return "resume";
      case StateChangeCommand::BACKGROUND:
        return "background";
      default:
        break;
    }
    return "unknown";
  }

  inline bool RequestForStateChange(
    const StateChangeCommand command) {
    bool result = false;

    SYSLOG(Logging::Notification, (_T("Cobalt request state change -> %s\n"), ToString(command)));

    switch (command) {
      case StateChangeCommand::SUSPEND: {
        if (_window.Suspend(true) == true) {
          result = true;
        }
        break;
      }
      case StateChangeCommand::RESUME: {
        // implies unpause
        if (_window.Suspend(false) == true) {
          result = true;
        }
        break;
      }
      case StateChangeCommand::BACKGROUND: {
        if (_window.Pause(true) == true) {
          result = true;
        }
        break;
      }
      default:
        ASSERT(false);
        break;
    }
    return result;
  }

  void StateChange(const PluginHost::IStateControl::state newState) {
    _adminLock.Lock();

    _state = newState;
    _statePending = PluginHost::IStateControl::UNINITIALIZED;

    std::list<PluginHost::IStateControl::INotification*>::iterator index(
      _stateControlClients.begin());

    while (index != _stateControlClients.end()) {
      (*index)->StateChange(newState);
      index++;
    }

    _adminLock.Unlock();
  }

  void NotifyClosure()
  {
    _adminLock.Lock();
    std::list<Exchange::IBrowser::INotification*>::iterator index(_cobaltClients.begin());
    while (index != _cobaltClients.end()) {
      (*index)->Closure();
      index++;
    }
    _adminLock.Unlock();
  }

private:
  CobaltWindow _window;
  mutable Core::CriticalSection _adminLock;
  PluginHost::IStateControl::state _state;
  PluginHost::IStateControl::state _statePending;
  std::list<Exchange::IBrowser::INotification*> _cobaltClients;
  std::list<PluginHost::IStateControl::INotification*> _stateControlClients;
  NotificationSink _sink;
  DelayedSuspend _delayedSuspend;
};

SERVICE_REGISTRATION(CobaltImplementation, 1, 0);

}  // namespace Plugin

}  // namespace WPEFramework
