// 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() const {
  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
