// Copyright 2020 The Cobalt Authors. All Rights Reserved.
//
// 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.

#include "cobalt/dom/lottie_player.h"

#include <memory>
#include <string>
#include <utility>

#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/document.h"
#include "cobalt/dom/dom_settings.h"
#include "cobalt/dom/html_element_context.h"
#include "cobalt/dom/lottie_frame_custom_event.h"
#include "cobalt/dom/window.h"
#include "cobalt/script/global_environment.h"
#include "cobalt/web/csp_delegate.h"
#include "url/gurl.h"

namespace cobalt {
namespace dom {

using render_tree::LottieAnimation;

const char LottiePlayer::kTagName[] = "lottie-player";

LottiePlayer::LottiePlayer(Document* document)
    : HTMLElement(document, base::Token(kTagName)),
      autoplaying_(true),
      ALLOW_THIS_IN_INITIALIZER_LIST(event_queue_(this)),
      callback_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
  SetAnimationEventCallbacks();
}

std::string LottiePlayer::src() const {
  return GetAttribute("src").value_or("");
}

void LottiePlayer::set_src(const std::string& src) { SetAttribute("src", src); }

bool LottiePlayer::autoplay() const { return GetBooleanAttribute("autoplay"); }

void LottiePlayer::set_autoplay(bool autoplay) {
  // The value of 'autoplay' is true when the 'autoplay' attribute is present.
  // The value of the attribute is irrelevant.
  if (autoplay) {
    SetBooleanAttribute("autoplay", true);
  } else {
    SetBooleanAttribute("autoplay", false);
  }
}

std::string LottiePlayer::background() const {
  return GetAttribute("background").value_or("");
}

void LottiePlayer::set_background(std::string background) {
  SetAttribute("background", background);
}

int LottiePlayer::count() const { return properties_.count; }

void LottiePlayer::set_count(int count) {
  SetAttribute("count", base::Int32ToString(count));
}

int LottiePlayer::direction() const { return properties_.direction; }

void LottiePlayer::set_direction(int direction) {
  SetAttribute("direction", base::Int32ToString(direction));
}

bool LottiePlayer::hover() const { return GetBooleanAttribute("hover"); }

void LottiePlayer::set_hover(bool hover) {
  // The value of 'hover' is true when the 'hover' attribute is present.
  // The value of the attribute is irrelevant.
  if (hover) {
    SetBooleanAttribute("hover", true);
  } else {
    SetBooleanAttribute("hover", false);
  }
}

bool LottiePlayer::loop() const { return properties_.loop; }

void LottiePlayer::set_loop(bool loop) {
  // The value of 'loop' is true when the 'loop' attribute is present.
  // The value of the attribute is irrelevant.
  if (loop) {
    SetBooleanAttribute("loop", true);
  } else {
    SetBooleanAttribute("loop", false);
  }
}

std::string LottiePlayer::mode() const { return properties_.GetModeAsString(); }

void LottiePlayer::set_mode(std::string mode) { SetAttribute("mode", mode); }

double LottiePlayer::speed() const { return properties_.speed; }

void LottiePlayer::set_speed(double speed) {
  SetAttribute("speed", base::NumberToString(speed));
}

std::string LottiePlayer::preserve_aspect_ratio() const {
  // Skottie animations default to "xMidYMid meet", meaning that the animation
  // will be uniformly scaled and centered relative to the element's width and
  // height.
  return "xMidYMid meet";
}

std::string LottiePlayer::renderer() const {
// Cobalt uses a custom compiled-in renderer.
#if defined(USE_SKIA_NEXT)
  return "skottie-m97";
#else
  return "skottie-m79";
#endif
}

void LottiePlayer::Load(std::string src) {
  // https://github.com/LottieFiles/lottie-player#loadsrc-string--object--void
  set_src(src);
}

void LottiePlayer::Play() {
  // https://lottiefiles.github.io/lottie-player/methods.html#play--void
  UpdateState(LottieAnimation::LottieState::kPlaying);
}

void LottiePlayer::Pause() {
  // https://lottiefiles.github.io/lottie-player/methods.html#pause--void
  UpdateState(LottieAnimation::LottieState::kPaused);
}

void LottiePlayer::Stop() {
  // https://lottiefiles.github.io/lottie-player/methods.html#stop--void
  UpdateState(LottieAnimation::LottieState::kStopped);
}

void LottiePlayer::Seek(FrameType frame) {
  // https://lottiefiles.github.io/lottie-player/methods.html#seekvalue-number--string--void
  if (frame.IsType<double>()) {
    properties_.SeekFrame(frame.AsType<double>());
  } else if (frame.IsType<std::string>()) {
    // Check whether a valid percent string.
    std::string frame_string = frame.AsType<std::string>();
    if (frame_string.empty()) {
      DLOG(WARNING) << "Percent string cannot be empty.";
      return;
    }
    double frame_percent;
    bool prefix_is_num = base::StringToDouble(
        frame_string.substr(0, frame_string.length() - 1), &frame_percent);
    if (frame_string.back() != '%' || !prefix_is_num) {
      DLOG(WARNING) << "Not a valid percent string: "
                    << frame.AsType<std::string>();
      return;
    }
    properties_.SeekPercent(frame_percent);
  }

  UpdateLottieObjects();
}

void LottiePlayer::SetDirection(int direction) {
  // https://lottiefiles.github.io/lottie-player/methods.html#setdirectionvalue-number--void
  if (properties_.UpdateDirection(direction)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::SetLooping(bool loop) {
  // https://lottiefiles.github.io/lottie-player/methods.html#setloopingvalue-boolean--void
  if (properties_.UpdateLoop(loop)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::SetSpeed(double speed) {
  // https://lottiefiles.github.io/lottie-player/methods.html#setspeedvalue-number--void
  if (properties_.UpdateSpeed(speed)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::ToggleLooping() {
  // https://github.com/LottieFiles/lottie-player#togglelooping--void
  properties_.ToggleLooping();
  UpdateLottieObjects();
}

void LottiePlayer::TogglePlay() {
  // https://github.com/LottieFiles/lottie-player#toggleplay--void
  properties_.TogglePlay();

  UpdateLottieObjects();
}

LottieAnimation::LottieProperties LottiePlayer::GetProperties() const {
  return properties_;
}

void LottiePlayer::OnHover() {
  if (hover()) {
    UpdateState(LottieAnimation::LottieState::kPlaying);
  }
}

void LottiePlayer::OnUnHover() {
  if (hover()) {
    UpdateState(LottieAnimation::LottieState::kStopped);
  }
}

void LottiePlayer::PurgeCachedBackgroundImagesOfNodeAndDescendants() {
  if (!cached_image_loaded_callback_handler_) {
    return;
  }

  // While we are still loading, treat this as an error.
  OnLoadingError();
}

void LottiePlayer::OnSetAttribute(const std::string& name,
                                  const std::string& value) {
  if (name == "src") {
    UpdateAnimationData();
  } else if (name == "background") {
    SetStyleAttribute("background:" + value);
  } else if (name == "count") {
    int count;
    base::StringToInt32(value, &count);
    SetCount(count);
  } else if (name == "direction") {
    int direction;
    base::StringToInt32(value, &direction);
    SetDirection(direction);
  } else if (name == "loop") {
    SetLooping(true);
  } else if (name == "mode") {
    SetMode(value);
  } else if (name == "speed") {
    double speed;
    base::StringToDouble(value, &speed);
    SetSpeed(speed);
  } else {
    HTMLElement::OnSetAttribute(name, value);
  }
}

void LottiePlayer::OnRemoveAttribute(const std::string& name) {
  if (name == "src") {
    UpdateAnimationData();
  } else if (name == "background") {
    SetStyleAttribute("background:transparent");
  } else if (name == "count") {
    SetCount(LottieAnimation::LottieProperties::kDefaultCount);
  } else if (name == "direction") {
    SetDirection(LottieAnimation::LottieProperties::kDefaultDirection);
  } else if (name == "loop") {
    SetLooping(LottieAnimation::LottieProperties::kDefaultLoop);
  } else if (name == "mode") {
    SetMode(LottieAnimation::LottieProperties::kDefaultMode);
  } else if (name == "speed") {
    SetSpeed(LottieAnimation::LottieProperties::kDefaultSpeed);
  } else {
    HTMLElement::OnRemoveAttribute(name);
  }
}

void LottiePlayer::UpdateAnimationData() {
  DCHECK(base::MessageLoop::current());
  DCHECK(node_document());
  TRACE_EVENT0("cobalt::dom", "LottiePlayer::UpdateAnimationData()");

  if (cached_image_loaded_callback_handler_) {
    cached_image_loaded_callback_handler_.reset();
    prevent_gc_until_load_complete_.reset();
    node_document()->DecreaseLoadingCounter();
  }

  const std::string src = GetAttribute("src").value_or("");

  if (!src.empty()) {
    const GURL& base_url = node_document()->location()->url();
    const GURL selected_source = base_url.Resolve(src);
    if (!selected_source.is_valid()) {
      LOG(WARNING) << src << " cannot be resolved based on " << base_url << ".";
      return;
    }

    auto image_cache = node_document()->html_element_context()->image_cache();
    cached_image_ = image_cache->GetOrCreateCachedResource(selected_source,
                                                           loader::Origin());

    if (cached_image_->TryGetResource()) {
      PreventGarbageCollectionUntilEventIsDispatched(base::Tokens::load());
      // The requested resource has already been loaded. Trigger the "load" and
      // "ready" events to indicate that the animation data is already loaded
      // and the DOM element is already ready.
      ScheduleEvent(base::Tokens::load());
      ScheduleEvent(base::Tokens::ready());
      return;
    }
  } else {
    PreventGarbageCollectionUntilEventIsDispatched(base::Tokens::error());
    return;
  }

  DCHECK(!prevent_gc_until_load_complete_);
  prevent_gc_until_load_complete_.reset(
      new script::GlobalEnvironment::ScopedPreventGarbageCollection(
          html_element_context()->script_runner()->GetGlobalEnvironment(),
          this));
  node_document()->IncreaseLoadingCounter();
  cached_image_loaded_callback_handler_.reset(
      new loader::image::CachedImage::OnLoadedCallbackHandler(
          cached_image_,
          base::Bind(&LottiePlayer::OnLoadingSuccess, base::Unretained(this)),
          base::Bind(&LottiePlayer::OnLoadingError, base::Unretained(this))));
}

void LottiePlayer::OnLoadingSuccess() {
  TRACE_EVENT0("cobalt::dom", "LottiePlayer::OnLoadingSuccess()");
  AllowGarbageCollectionAfterEventIsDispatched(
      base::Tokens::load(), std::move(prevent_gc_until_load_complete_));
  if (node_document()) {
    node_document()->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
  }
  cached_image_loaded_callback_handler_.reset();

  // Set up the Lottie objects in the box and render trees once the file has
  // successfully loaded.
  UpdateLottieObjects();
  // Trigger a load event to indicate that the animation data has loaded, and
  // then a "ready" event to indicate the DOM element is ready.
  ScheduleEvent(base::Tokens::load());
  ScheduleEvent(base::Tokens::ready());
  // If the animation is autoplaying and autoplay is true, then the animation
  // playback state needs to be set to LottieAnimation::LottieState::kPlaying.
  UpdatePlaybackStateIfAutoplaying();
}

void LottiePlayer::OnLoadingError() {
  TRACE_EVENT0("cobalt::dom", "LottiePlayer::OnLoadingError()");
  AllowGarbageCollectionAfterEventIsDispatched(
      base::Tokens::error(), std::move(prevent_gc_until_load_complete_));
  if (node_document()) {
    node_document()->DecreaseLoadingCounterAndMaybeDispatchLoadEvent();
  }
  cached_image_loaded_callback_handler_.reset();
  ScheduleEvent(base::Tokens::error());
}

void LottiePlayer::PreventGarbageCollectionUntilEventIsDispatched(
    base::Token event_name) {
  std::unique_ptr<script::GlobalEnvironment::ScopedPreventGarbageCollection>
      prevent_gc_until_event_dispatch(
          new script::GlobalEnvironment::ScopedPreventGarbageCollection(
              html_element_context()->script_runner()->GetGlobalEnvironment(),
              this));
  AllowGarbageCollectionAfterEventIsDispatched(
      event_name, std::move(prevent_gc_until_event_dispatch));
}

void LottiePlayer::AllowGarbageCollectionAfterEventIsDispatched(
    base::Token event_name,
    std::unique_ptr<script::GlobalEnvironment::ScopedPreventGarbageCollection>
        scoped_prevent_gc) {
  PostToDispatchEventNameAndRunCallback(
      FROM_HERE, event_name,
      base::Bind(&LottiePlayer::DestroyScopedPreventGC,
                 base::AsWeakPtr<LottiePlayer>(this),
                 base::Passed(&scoped_prevent_gc)));
}

void LottiePlayer::DestroyScopedPreventGC(
    std::unique_ptr<script::GlobalEnvironment::ScopedPreventGarbageCollection>
        scoped_prevent_gc) {
  scoped_prevent_gc.reset();
}

void LottiePlayer::UpdateState(LottieAnimation::LottieState state) {
  if (properties_.UpdateState(state)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::UpdatePlaybackStateIfAutoplaying() {
  if (autoplaying_ && autoplay()) {
    properties_.UpdateState(LottieAnimation::LottieState::kPlaying);
  }
  autoplaying_ = false;
}

void LottiePlayer::SetCount(int count) {
  if (properties_.UpdateCount(count)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::SetMode(std::string mode) {
  if (properties_.UpdateMode(mode)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::SetMode(LottieAnimation::LottieMode mode) {
  if (properties_.UpdateMode(mode)) {
    UpdateLottieObjects();
  }
}

void LottiePlayer::UpdateLottieObjects() {
  node_document()->RecordMutation();
  InvalidateLayoutBoxesOfNodeAndAncestors();
}

void LottiePlayer::ScheduleEvent(base::Token event_name) {
  // https://github.com/LottieFiles/lottie-player#events
  scoped_refptr<web::Event> event = new web::Event(event_name);
  event->set_target(this);
  event_queue_.Enqueue(event);
}

void LottiePlayer::SetAnimationEventCallbacks() {
  DCHECK(callback_task_runner_);
  properties_.onplay_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnPlay, base::AsWeakPtr(this)));
  properties_.onpause_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnPause, base::AsWeakPtr(this)));
  properties_.onstop_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnStop, base::AsWeakPtr(this)));
  properties_.oncomplete_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnComplete, base::AsWeakPtr(this)));
  properties_.onloop_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnLoop, base::AsWeakPtr(this)));
  properties_.onenterframe_callback = base::Bind(
      &LottiePlayer::CallOnEnterFrame, callback_task_runner_,
      base::Bind(&LottiePlayer::OnEnterFrame, base::AsWeakPtr(this)));
  properties_.onfreeze_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnFreeze, base::AsWeakPtr(this)));
  properties_.onunfreeze_callback =
      base::Bind(base::IgnoreResult(&base::SingleThreadTaskRunner::PostTask),
                 callback_task_runner_, FROM_HERE,
                 base::Bind(&LottiePlayer::OnUnfreeze, base::AsWeakPtr(this)));
}

void LottiePlayer::OnPlay() { ScheduleEvent(base::Tokens::play()); }

void LottiePlayer::OnPause() { ScheduleEvent(base::Tokens::pause()); }

void LottiePlayer::OnStop() { ScheduleEvent(base::Tokens::stop()); }

void LottiePlayer::OnComplete() { ScheduleEvent(base::Tokens::complete()); }

void LottiePlayer::OnLoop() { ScheduleEvent(base::Tokens::loop()); }

void LottiePlayer::OnEnterFrame(double frame, double seeker) {
  LottieFrameCustomEventDetail detail;
  detail.set_frame(frame);
  detail.set_seeker(seeker);

  scoped_refptr<LottieFrameCustomEvent> lottie_frame_custom_event =
      new LottieFrameCustomEvent("frame");
  lottie_frame_custom_event->set_detail(detail);
  lottie_frame_custom_event->set_target(this);
  event_queue_.Enqueue(lottie_frame_custom_event);
}

void LottiePlayer::CallOnEnterFrame(
    scoped_refptr<base::SingleThreadTaskRunner> callback_task_runner,
    base::Callback<void(double, double)> enter_frame_callback, double frame,
    double seeker) {
  callback_task_runner->PostTask(
      FROM_HERE, base::Bind(enter_frame_callback, frame, seeker));
}

void LottiePlayer::OnFreeze() {
  if (properties_.FreezeAnimationState()) {
    ScheduleEvent(base::Tokens::freeze());
    UpdateLottieObjects();
  }
}

void LottiePlayer::OnUnfreeze() {
  if (properties_.UnfreezeAnimationState()) {
    ScheduleEvent(base::Tokens::play());
    UpdateLottieObjects();
  }
}

}  // namespace dom
}  // namespace cobalt
