// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define FML_USED_ON_EMBEDDER

#include "flutter/fml/raster_thread_merger.h"

#include "flutter/fml/message_loop_impl.h"

namespace fml {

RasterThreadMerger::RasterThreadMerger(fml::TaskQueueId platform_queue_id,
                                       fml::TaskQueueId gpu_queue_id)
    : RasterThreadMerger(
          MakeRefCounted<SharedThreadMerger>(platform_queue_id, gpu_queue_id),
          platform_queue_id,
          gpu_queue_id) {}

RasterThreadMerger::RasterThreadMerger(
    fml::RefPtr<fml::SharedThreadMerger> shared_merger,
    fml::TaskQueueId platform_queue_id,
    fml::TaskQueueId gpu_queue_id)
    : platform_queue_id_(platform_queue_id),
      gpu_queue_id_(gpu_queue_id),
      shared_merger_(shared_merger) {}

void RasterThreadMerger::SetMergeUnmergeCallback(const fml::closure& callback) {
  merge_unmerge_callback_ = callback;
}

const fml::RefPtr<fml::SharedThreadMerger>&
RasterThreadMerger::GetSharedRasterThreadMerger() const {
  return shared_merger_;
}

fml::RefPtr<fml::RasterThreadMerger>
RasterThreadMerger::CreateOrShareThreadMerger(
    const fml::RefPtr<fml::RasterThreadMerger>& parent_merger,
    TaskQueueId platform_id,
    TaskQueueId raster_id) {
  if (parent_merger && parent_merger->platform_queue_id_ == platform_id &&
      parent_merger->gpu_queue_id_ == raster_id) {
    auto shared_merger = parent_merger->GetSharedRasterThreadMerger();
    return fml::MakeRefCounted<RasterThreadMerger>(shared_merger, platform_id,
                                                   raster_id);
  } else {
    return fml::MakeRefCounted<RasterThreadMerger>(platform_id, raster_id);
  }
}

void RasterThreadMerger::MergeWithLease(size_t lease_term) {
  std::scoped_lock lock(mutex_);
  if (TaskQueuesAreSame()) {
    return;
  }
  if (!IsEnabledUnSafe()) {
    return;
  }
  FML_DCHECK(lease_term > 0) << "lease_term should be positive.";

  if (IsMergedUnSafe()) {
    merged_condition_.notify_one();
    return;
  }

  bool success = shared_merger_->MergeWithLease(this, lease_term);
  if (success && merge_unmerge_callback_ != nullptr) {
    merge_unmerge_callback_();
  }

  merged_condition_.notify_one();
}

void RasterThreadMerger::UnMergeNowIfLastOne() {
  std::scoped_lock lock(mutex_);

  if (TaskQueuesAreSame()) {
    return;
  }
  if (!IsEnabledUnSafe()) {
    return;
  }
  bool success = shared_merger_->UnMergeNowIfLastOne(this);
  if (success && merge_unmerge_callback_ != nullptr) {
    merge_unmerge_callback_();
  }
}

bool RasterThreadMerger::IsOnPlatformThread() const {
  return MessageLoop::GetCurrentTaskQueueId() == platform_queue_id_;
}

bool RasterThreadMerger::IsOnRasterizingThread() {
  std::scoped_lock lock(mutex_);

  if (IsMergedUnSafe()) {
    return IsOnPlatformThread();
  } else {
    return !IsOnPlatformThread();
  }
}

void RasterThreadMerger::ExtendLeaseTo(size_t lease_term) {
  FML_DCHECK(lease_term > 0) << "lease_term should be positive.";
  if (TaskQueuesAreSame()) {
    return;
  }
  std::scoped_lock lock(mutex_);
  if (!IsEnabledUnSafe()) {
    return;
  }
  shared_merger_->ExtendLeaseTo(this, lease_term);
}

bool RasterThreadMerger::IsMerged() {
  std::scoped_lock lock(mutex_);
  return IsMergedUnSafe();
}

void RasterThreadMerger::Enable() {
  std::scoped_lock lock(mutex_);
  shared_merger_->SetEnabledUnSafe(true);
}

void RasterThreadMerger::Disable() {
  std::scoped_lock lock(mutex_);
  shared_merger_->SetEnabledUnSafe(false);
}

bool RasterThreadMerger::IsEnabled() {
  std::scoped_lock lock(mutex_);
  return IsEnabledUnSafe();
}

bool RasterThreadMerger::IsEnabledUnSafe() const {
  return shared_merger_->IsEnabledUnSafe();
}

bool RasterThreadMerger::IsMergedUnSafe() const {
  return TaskQueuesAreSame() || shared_merger_->IsMergedUnSafe();
}

bool RasterThreadMerger::TaskQueuesAreSame() const {
  return platform_queue_id_ == gpu_queue_id_;
}

void RasterThreadMerger::WaitUntilMerged() {
  if (TaskQueuesAreSame()) {
    return;
  }
  FML_CHECK(IsOnPlatformThread());
  std::unique_lock<std::mutex> lock(mutex_);
  merged_condition_.wait(lock, [&] { return IsMergedUnSafe(); });
}

RasterThreadStatus RasterThreadMerger::DecrementLease() {
  if (TaskQueuesAreSame()) {
    return RasterThreadStatus::kRemainsMerged;
  }
  std::scoped_lock lock(mutex_);
  if (!IsMergedUnSafe()) {
    return RasterThreadStatus::kRemainsUnmerged;
  }
  if (!IsEnabledUnSafe()) {
    return RasterThreadStatus::kRemainsMerged;
  }
  bool unmerged_after_decrement = shared_merger_->DecrementLease(this);
  if (unmerged_after_decrement) {
    if (merge_unmerge_callback_ != nullptr) {
      merge_unmerge_callback_();
    }
    return RasterThreadStatus::kUnmergedNow;
  }

  return RasterThreadStatus::kRemainsMerged;
}

}  // namespace fml
