// Copyright 2025 The Pigweed Authors
//
// 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
//
//     https://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 "pw_bluetooth_proxy/config.h"

#if PW_BLUETOOTH_PROXY_ASYNC != 0

#include "pw_assert/check.h"
#include "pw_bluetooth_proxy_private/test_utils.h"
#include "pw_status/try.h"

namespace pw::bluetooth::proxy {

////////////////////////////////////////////////////////////////////////////////
// ProxyHostTestDispatcher methods.

ProxyHostTestDispatcher::~ProxyHostTestDispatcher() {
  PW_CHECK(!thread_.has_value(),
           "The dispatcher thread must be joined before test completes.");
}

void ProxyHostTestDispatcher::StartOnCurrentThread(ProxyHost& proxy) {
  proxy_ = &proxy;
  {
    std::lock_guard lock(mutex_);
    PW_CHECK(!id_.has_value());
    id_ = this_thread::get_id();
  }
  PW_CHECK_OK(proxy_->SetDispatcher(dispatcher_));
}

bool ProxyHostTestDispatcher::IsRunningOnThisThread() const {
  std::lock_guard lock(mutex_);
  PW_CHECK(id_.has_value());
  return this_thread::get_id() == *id_;
}

void ProxyHostTestDispatcher::Run() {
  if (IsRunningOnThisThread()) {
    dispatcher_.RunUntilStalled();
  } else {
    // Clear any latch set by a previously completed run of the dispatcher.
    std::ignore = tx_.try_acquire();
    rx_.release();
    tx_.acquire();
  }
}

#if PW_THREAD_JOINING_ENABLED

void ProxyHostTestDispatcher::StartOnNewThread(ProxyHost& proxy) {
  proxy_ = &proxy;
  thread_.emplace(context_.options(), [this]() {
    {
      std::lock_guard lock(mutex_);
      PW_CHECK(!id_.has_value());
      id_ = this_thread::get_id();
    }
    PW_CHECK_OK(proxy_->SetDispatcher(dispatcher_));
    tx_.release();
    while (true) {
      rx_.acquire();
      dispatcher_.RunUntilStalled();
      tx_.release();
      std::lock_guard lock(mutex_);
      if (!id_.has_value()) {
        break;
      }
    }
  });

  // Make sure the dispatcher is set before returning.
  tx_.acquire();
}

void ProxyHostTestDispatcher::JoinThread() {
  if (!thread_.has_value()) {
    return;
  }
  {
    std::lock_guard lock(mutex_);
    id_.reset();
  }
  rx_.release();
  thread_->join();
  thread_.reset();
}

#endif  // PW_THREAD_JOINING_ENABLED

////////////////////////////////////////////////////////////////////////////////
// ProxyHostTest methods.

void ProxyHostTest::StartDispatcherOnCurrentThread(ProxyHost& proxy) {
  dispatcher_.StartOnCurrentThread(proxy);
}

void ProxyHostTest::StartDispatcherOnNewThread(ProxyHost& proxy) {
  dispatcher_.StartOnNewThread(proxy);
}

void ProxyHostTest::RunDispatcher() { dispatcher_.Run(); }

void ProxyHostTest::JoinDispatcherThread() { dispatcher_.JoinThread(); }

}  // namespace pw::bluetooth::proxy

#endif  // PW_BLUETOOTH_PROXY_ASYNC
