/**
* 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 "Cobalt.h"

namespace WPEFramework {

namespace Cobalt {

extern Exchange::IMemory* MemoryObserver(const RPC::IRemoteConnection* connection);

}  // namespace Cobalt

namespace Plugin {

SERVICE_REGISTRATION(Cobalt, 1, 0);

static Core::ProxyPoolType<Web::TextBody> _textBodies(2);
static Core::ProxyPoolType<Web::JSONBodyType<Cobalt::Data>> jsonBodyDataFactory(2);

/* encapsulated class Thread  */
const string Cobalt::Initialize(PluginHost::IShell *service) {
  Config config;
  string message;

  ASSERT(_service == nullptr);
  ASSERT(_cobalt == nullptr);
  ASSERT(_memory == nullptr);

  config.FromString(service->ConfigLine());

  _connectionId = 0;
  _service = service;
  _skipURL = _service->WebPrefix().length();

  // Register the Connection::Notification stuff. The Remote process might die
  // before we get a
  // change to "register" the sink for these events !!! So do it ahead of
  // instantiation.
  _service->Register(&_notification);
  _cobalt = _service->Root < Exchange::IBrowser > (_connectionId, 2000, _T("CobaltImplementation"));

  if (_cobalt != nullptr) {
    PluginHost::IStateControl *stateControl(
      _cobalt->QueryInterface<PluginHost::IStateControl>());
    if (stateControl == nullptr) {
      _cobalt->Release();
      _cobalt = nullptr;
    } else {
      RPC::IRemoteConnection* remoteConnection = _service->RemoteConnection(_connectionId);
      _memory = WPEFramework::Cobalt::MemoryObserver(remoteConnection);
      ASSERT(_memory != nullptr);
      if (remoteConnection)
        remoteConnection->Release();

      _cobalt->Register(&_notification);
      stateControl->Register(&_notification);
      stateControl->Configure(_service);
      stateControl->Release();
    }
  }

  if (_cobalt == nullptr) {
    message = _T("Cobalt could not be instantiated.");
    _service->Unregister(&_notification);
    ConnectionTermination(_connectionId);
    _service = nullptr;
  }

  return message;
}

void Cobalt::Deinitialize(PluginHost::IShell *service) {
  ASSERT(_service == service);
  ASSERT(_cobalt != nullptr);
  ASSERT(_memory != nullptr);

  if (_cobalt == nullptr)
      return;

  PluginHost::IStateControl *stateControl(
    _cobalt->QueryInterface<PluginHost::IStateControl>());

  // Make sure the Activated and Deactivated are no longer called before we
  // start cleaning up..
  _service->Unregister(&_notification);
  _cobalt->Unregister(&_notification);
  _memory->Release();

  // In case Cobalt crashed, there is no access to the statecontrol interface,
  // check it !!
  if (stateControl != nullptr) {
    stateControl->Unregister(&_notification);
    stateControl->Release();
  } else {
    // On behalf of the crashed process, we will release the notification sink.
    _notification.Release();
  }

  if (_cobalt->Release() != Core::ERROR_DESTRUCTION_SUCCEEDED) {
    ASSERT(_connectionId != 0);
    TRACE_L1("Cobalt Plugin is not properly destructed. %d", _connectionId);
    ConnectionTermination(_connectionId);
  }

  // Deinitialize what we initialized..
  _memory = nullptr;
  _cobalt = nullptr;
  _service = nullptr;
}

string Cobalt::Information() const {
  // No additional info to report.
  return (string());
}

void Cobalt::Inbound(Web::Request &request) {
  if (request.Verb == Web::Request::HTTP_POST) {
    // This might be a "launch" application thingy, make sure we receive the
    // proper info.
    request.Body(jsonBodyDataFactory.Element());
  }
}

Core::ProxyType<Web::Response> Cobalt::Process(const Web::Request &request) {
  ASSERT(_skipURL <= request.Path.length());
  TRACE(Trace::Information, (string(_T("Received cobalt request"))));

  Core::ProxyType<Web::Response> result(PluginHost::IFactories::Instance().Response());

  Core::TextSegmentIterator index(
    Core::TextFragment(request.Path, _skipURL,
                       request.Path.length() - _skipURL), false, '/');

  result->ErrorCode = Web::STATUS_BAD_REQUEST;
  result->Message = "Unknown error";

  if (request.Verb == Web::Request::HTTP_POST) {
    // We might be receiving a plugin download request.
    if ((index.Next() == true) && (index.Next() == true)
        && (_cobalt != nullptr)) {
      PluginHost::IStateControl *stateControl(
        _cobalt->QueryInterface<PluginHost::IStateControl>());
      if (stateControl != nullptr) {
        if (index.Remainder() == _T("Suspend")) {
          stateControl->Request(PluginHost::IStateControl::SUSPEND);
        } else if (index.Remainder() == _T("Resume")) {
          stateControl->Request(PluginHost::IStateControl::RESUME);
        } else if ((index.Remainder() == _T("URL"))
                   && (request.HasBody() == true)
                   && (request.Body<const Data>()->URL.Value().empty()
                       == false)) {
          _cobalt->SetURL(request.Body<const Data>()->URL.Value());
        }
        stateControl->Release();
      }
    }
  }
  else if (request.Verb == Web::Request::HTTP_GET) {
  }
  return result;
}

void Cobalt::LoadFinished(const string &URL) {
  string message(
    string("{ \"url\": \"") + URL + string("\", \"loaded\":true }"));
  TRACE(Trace::Information, (_T("LoadFinished: %s"), message.c_str()));
  _service->Notify(message);

  event_urlchange(URL, true);
}

void Cobalt::URLChanged(const string &URL) {
  string message(string("{ \"url\": \"") + URL + string("\" }"));
  TRACE(Trace::Information, (_T("URLChanged: %s"), message.c_str()));
  _service->Notify(message);

  event_urlchange(URL, false);
}

void Cobalt::Hidden(const bool hidden) {
  TRACE(Trace::Information,
        (_T("Hidden: %s }"), (hidden ? "true" : "false")));
  string message(
    string("{ \"hidden\": ") + (hidden ? _T("true") : _T("false"))
    + string("}"));
  _hidden = hidden;
  _service->Notify(message);

  event_visibilitychange(hidden);
}

void Cobalt::StateChange(const PluginHost::IStateControl::state state) {
  switch (state) {
    case PluginHost::IStateControl::RESUMED:
      TRACE(Trace::Information,
            (string(_T("StateChange: { \"suspend\":false }"))));
      _service->Notify("{ \"suspended\":false }");
      event_statechange(false);
      break;
    case PluginHost::IStateControl::SUSPENDED:
      TRACE(Trace::Information,
            (string(_T("StateChange: { \"suspend\":true }"))));
      _service->Notify("{ \"suspended\":true }");
      event_statechange(true);
      break;
    case PluginHost::IStateControl::EXITED:
      // Exited by Cobalt app
      Core::IWorkerPool::Instance().Submit(
        PluginHost::IShell::Job::Create(_service,
                                        PluginHost::IShell::DEACTIVATED,
                                        PluginHost::IShell::REQUESTED));
      break;
    case PluginHost::IStateControl::UNINITIALIZED:
      break;
    default:
      ASSERT(false);
      break;
  }
}

void Cobalt::Deactivated(RPC::IRemoteConnection *connection) {
  if (connection->Id() == _connectionId) {
    ASSERT(_service != nullptr);
    Core::IWorkerPool::Instance().Submit(
      PluginHost::IShell::Job::Create(_service,
        PluginHost::IShell::DEACTIVATED,
        PluginHost::IShell::FAILURE));
  }
}

}  // namespace Plugin
}  // namespace WPEFramework
