// Copyright 2019 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/ui_navigation/nav_item.h"

#include <vector>

#include "base/bind.h"
#include "starboard/atomic.h"
#include "starboard/common/spin_lock.h"

namespace cobalt {
namespace ui_navigation {

namespace {
// These data structures support queuing of UI navigation changes so they can
// be executed as a batch to atomically update the UI.
SbAtomic32 g_pending_updates_lock(starboard::kSpinLockStateReleased);

struct PendingUpdate {
  PendingUpdate(NativeItem nav_item, const base::Closure& closure)
      : nav_item(nav_item), closure(closure) {}
  NativeItem nav_item;
  base::Closure closure;
};
std::vector<PendingUpdate>* g_pending_updates = nullptr;

// Pending focus change should always be done after all updates. This ensures
// the focus target is up-to-date.
volatile NativeItem g_pending_focus = kNativeItemInvalid;

// This tracks the total number of NavItems. It is used to control allocation
// and deletion of data for queued updates.
int32_t g_nav_item_count = 0;

// This helper function is necessary to preserve the |transform| by value.
void SetTransformHelper(NativeItem native_item, NativeMatrix2x3 transform) {
  GetInterface().set_item_transform(native_item, &transform);
}

// This processes all pending updates specified by the given context. The update
// list should already be locked from modifications by other threads.
void ProcessPendingChanges(void* context) {
  std::vector<PendingUpdate>* updates =
      static_cast<std::vector<PendingUpdate>*>(context);
  for (size_t i = 0; i < updates->size(); ++i) {
    (*updates)[i].closure.Run();
  }
  updates->clear();
}

// Remove any pending changes associated with the specified item.
void RemovePendingChangesLocked(NativeItem nav_item) {
  DCHECK(nav_item != kNativeItemInvalid);

  for (size_t i = 0; i < g_pending_updates->size();) {
    if ((*g_pending_updates)[i].nav_item == nav_item) {
      g_pending_updates->erase(g_pending_updates->begin() + i);
      continue;
    }
    ++i;
  }

  if (g_pending_focus == nav_item) {
    g_pending_focus = kNativeItemInvalid;
  }
}

}  // namespace

// Use an atomic to track the currently-focused item. Don't use a mutex or
// spinlock in GetGlobalFocusTransform() / GetGlobalFocusVector() and
// OnBlur() / OnFocus() since this can result in a deadlock if the starboard
// implementation uses a lock of its own for the NativeItem.
SbAtomicPtr NavItem::s_focused_nav_item_(
    reinterpret_cast<intptr_t>(kNativeItemInvalid));

NativeCallbacks NavItem::s_callbacks_ = {
    &NavItem::OnBlur, &NavItem::OnFocus, &NavItem::OnScroll,
};

NavItem::NavItem(NativeItemType type, const base::Closure& onblur_callback,
                 const base::Closure& onfocus_callback,
                 const base::Closure& onscroll_callback)
    : onblur_callback_(onblur_callback),
      onfocus_callback_(onfocus_callback),
      onscroll_callback_(onscroll_callback),
      nav_item_type_(type),
      nav_item_(GetInterface().create_item(type, &s_callbacks_, this)),
      state_(kStateNew) {
  static_assert(sizeof(s_focused_nav_item_) == sizeof(NativeItem),
                "Size mismatch");
  static_assert(sizeof(s_focused_nav_item_) == sizeof(intptr_t),
                "Size mismatch");
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  if (++g_nav_item_count == 1) {
    g_pending_updates = new std::vector<PendingUpdate>();
    g_pending_focus = kNativeItemInvalid;
  }
}

NavItem::~NavItem() {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  DCHECK(state_ == kStatePendingDelete);
  DCHECK(SbAtomicNoBarrier_LoadPtr(&s_focused_nav_item_) !=
         reinterpret_cast<intptr_t>(nav_item_));
  g_pending_updates->emplace_back(
      nav_item_, base::Bind(GetInterface().destroy_item, nav_item_));
  if (--g_nav_item_count == 0) {
    DCHECK(g_pending_focus == kNativeItemInvalid);
    ProcessPendingChanges(g_pending_updates);
    delete g_pending_updates;
    g_pending_updates = nullptr;
  }
}

void NavItem::PerformQueuedUpdates() {
  std::vector<PendingUpdate> updates_snapshot;

  // Process only the updates that have been queued up to this point. Other
  // threads may be queueing more updates, and we shouldn't pick them up in this
  // batch as that may result in them getting processed before async tasks that
  // may be done by the platform.
  {
    starboard::ScopedSpinLock lock(&g_pending_updates_lock);
    updates_snapshot.swap(*g_pending_updates);
    if (g_pending_focus != kNativeItemInvalid) {
      updates_snapshot.emplace_back(
          g_pending_focus,
          base::Bind(GetInterface().set_focus, g_pending_focus));
      g_pending_focus = kNativeItemInvalid;
    }
  }

  GetInterface().do_batch_update(&ProcessPendingChanges, &updates_snapshot);
}

void NavItem::Focus() {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  if (state_ == kStateEnabled) {
    if (g_pending_updates->empty()) {
      // Immediately update focus if nothing else is queued for update.
      g_pending_focus = kNativeItemInvalid;
      GetInterface().set_focus(nav_item_);
    } else {
      g_pending_focus = nav_item_;
    }
  }
}

void NavItem::UnfocusAll() {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  g_pending_focus = kNativeItemInvalid;
#if SB_API_VERSION >= SB_UI_NAVIGATION2_VERSION
  g_pending_updates->emplace_back(
      kNativeItemInvalid,
      base::Bind(GetInterface().set_focus, kNativeItemInvalid));
#endif
}

void NavItem::SetEnabled(bool enabled) {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  if (enabled) {
    if (state_ == kStateNew) {
      state_ = kStateEnabled;
      g_pending_updates->emplace_back(
          nav_item_,
          base::Bind(GetInterface().set_item_enabled, nav_item_, enabled));
    }
  } else {
    if (state_ != kStatePendingDelete) {
      state_ = kStatePendingDelete;
      // Remove any pending changes associated with this item.
      RemovePendingChangesLocked(nav_item_);
      // Disable immediately to avoid errant callbacks on this item.
      GetInterface().set_item_enabled(nav_item_, enabled);
    }
    SbAtomicNoBarrier_CompareAndSwapPtr(
        &s_focused_nav_item_, reinterpret_cast<intptr_t>(nav_item_),
        reinterpret_cast<intptr_t>(kNativeItemInvalid));
  }
}

void NavItem::SetDir(NativeItemDir dir) {
  // Do immediately in case it impacts content offset queries.
  GetInterface().set_item_dir(nav_item_, dir);
}

void NavItem::SetFocusDuration(float seconds) {
  GetInterface().set_item_focus_duration(nav_item_, seconds);
}

void NavItem::SetSize(float width, float height) {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  g_pending_updates->emplace_back(
      nav_item_,
      base::Bind(GetInterface().set_item_size, nav_item_, width, height));
}

void NavItem::SetTransform(const NativeMatrix2x3* transform) {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  g_pending_updates->emplace_back(
      nav_item_, base::Bind(&SetTransformHelper, nav_item_, *transform));
}

bool NavItem::GetFocusTransform(NativeMatrix4* out_transform) {
  return GetInterface().get_item_focus_transform(nav_item_, out_transform);
}

bool NavItem::GetFocusVector(float* out_x, float* out_y) {
  return GetInterface().get_item_focus_vector(nav_item_, out_x, out_y);
}

void NavItem::SetContainerWindow(SbWindow window) {
  // Do immediately since the lifetime of |window| is not guaranteed after this
  // call.
  GetInterface().set_item_container_window(nav_item_, window);
}

void NavItem::SetContainerItem(const scoped_refptr<NavItem>& container) {
  // Set the container immediately so that subsequent calls to GetContainerItem
  // are correct. However, the actual nav_item_ change should still be queued.
  container_ = container;
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  g_pending_updates->emplace_back(
      nav_item_,
      base::Bind(GetInterface().set_item_container_item, nav_item_,
                 container ? container->nav_item_ : kNativeItemInvalid));
}

const scoped_refptr<NavItem>& NavItem::GetContainerItem() const {
  return container_;
}

void NavItem::SetContentOffset(float x, float y) {
  // Do immediately since content offset may be queried immediately after.
  GetInterface().set_item_content_offset(nav_item_, x, y);
}

void NavItem::GetContentOffset(float* out_x, float* out_y) {
  GetInterface().get_item_content_offset(nav_item_, out_x, out_y);
}

// static
bool NavItem::GetGlobalFocusTransform(NativeMatrix4* out_transform) {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  NativeItem focused_item = reinterpret_cast<NativeItem>(
      SbAtomicNoBarrier_LoadPtr(&s_focused_nav_item_));
  if (focused_item == kNativeItemInvalid) {
    return false;
  }
  return GetInterface().get_item_focus_transform(focused_item, out_transform);
}

// static
bool NavItem::GetGlobalFocusVector(float* out_x, float* out_y) {
  starboard::ScopedSpinLock lock(&g_pending_updates_lock);
  NativeItem focused_item = reinterpret_cast<NativeItem>(
      SbAtomicNoBarrier_LoadPtr(&s_focused_nav_item_));
  if (focused_item == kNativeItemInvalid) {
    return false;
  }
  return GetInterface().get_item_focus_vector(focused_item, out_x, out_y);
}

// static
void NavItem::OnBlur(NativeItem item, void* callback_context) {
  NavItem* this_ptr = static_cast<NavItem*>(callback_context);
  SbAtomicNoBarrier_CompareAndSwapPtr(
      &s_focused_nav_item_, reinterpret_cast<intptr_t>(this_ptr->nav_item_),
      reinterpret_cast<intptr_t>(kNativeItemInvalid));
  if (!this_ptr->onblur_callback_.is_null()) {
    this_ptr->onblur_callback_.Run();
  }
}

// static
void NavItem::OnFocus(NativeItem item, void* callback_context) {
  NavItem* this_ptr = static_cast<NavItem*>(callback_context);
  SbAtomicNoBarrier_StorePtr(&s_focused_nav_item_,
                             reinterpret_cast<intptr_t>(this_ptr->nav_item_));
  if (!this_ptr->onfocus_callback_.is_null()) {
    this_ptr->onfocus_callback_.Run();
  }
}

// static
void NavItem::OnScroll(NativeItem item, void* callback_context) {
  NavItem* this_ptr = static_cast<NavItem*>(callback_context);
  if (!this_ptr->onscroll_callback_.is_null()) {
    this_ptr->onscroll_callback_.Run();
  }
}

}  // namespace ui_navigation
}  // namespace cobalt
