/*
 * Copyright 2019 The Android Open Source Project
 *
 * 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 <condition_variable>
#include <cstdint>
#include <unordered_map>

#include "common/bidi_queue.h"
#include "common/bind.h"
#include "common/callback.h"
#include "grpc/grpc_event_queue.h"
#include "hci/address.h"
#include "l2cap/classic/facade.grpc.pb.h"
#include "l2cap/classic/facade.h"
#include "l2cap/classic/l2cap_classic_module.h"
#include "os/log.h"
#include "packet/raw_builder.h"

using ::grpc::ServerAsyncResponseWriter;
using ::grpc::ServerAsyncWriter;
using ::grpc::ServerContext;

using ::bluetooth::packet::RawBuilder;

namespace bluetooth {
namespace l2cap {
namespace classic {

class L2capClassicModuleFacadeService : public L2capClassicModuleFacade::Service, public LinkSecurityInterfaceListener {
 public:
  L2capClassicModuleFacadeService(L2capClassicModule* l2cap_layer, os::Handler* facade_handler)
      : l2cap_layer_(l2cap_layer), facade_handler_(facade_handler), security_interface_(nullptr) {
    ASSERT(l2cap_layer_ != nullptr);
    ASSERT(facade_handler_ != nullptr);
  }

  ::grpc::Status FetchConnectionComplete(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                         ::grpc::ServerWriter<classic::ConnectionCompleteEvent>* writer) override {
    return pending_connection_complete_.RunLoop(context, writer);
  }

  ::grpc::Status FetchConnectionClose(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                      ::grpc::ServerWriter<classic::ConnectionCloseEvent>* writer) override {
    return pending_connection_close_.RunLoop(context, writer);
  }

  ::grpc::Status SendDynamicChannelPacket(::grpc::ServerContext* context, const DynamicChannelPacket* request,
                                          ::google::protobuf::Empty* response) override {
    std::unique_lock<std::mutex> lock(channel_map_mutex_);
    if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) {
      return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
    }
    std::vector<uint8_t> packet(request->payload().begin(), request->payload().end());
    if (!dynamic_channel_helper_map_[request->psm()]->SendPacket(packet)) {
      return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open");
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status OpenChannel(::grpc::ServerContext* context,
                             const ::bluetooth::l2cap::classic::OpenChannelRequest* request,
                             ::google::protobuf::Empty* response) override {
    auto service_helper = dynamic_channel_helper_map_.find(request->psm());
    if (service_helper == dynamic_channel_helper_map_.end()) {
      return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
    }
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->remote().address(), peer));
    dynamic_channel_helper_map_[request->psm()]->Connect(peer);
    return ::grpc::Status::OK;
  }

  ::grpc::Status CloseChannel(::grpc::ServerContext* context,
                              const ::bluetooth::l2cap::classic::CloseChannelRequest* request,
                              ::google::protobuf::Empty* response) override {
    auto psm = request->psm();
    if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) {
      return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
    }
    dynamic_channel_helper_map_[psm]->Disconnect();
    return ::grpc::Status::OK;
  }

  ::grpc::Status FetchL2capData(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                ::grpc::ServerWriter<classic::L2capPacket>* writer) override {
    auto status = pending_l2cap_data_.RunLoop(context, writer);

    return status;
  }

  ::grpc::Status SetDynamicChannel(::grpc::ServerContext* context, const SetEnableDynamicChannelRequest* request,
                                   google::protobuf::Empty* response) override {
    dynamic_channel_helper_map_.emplace(
        request->psm(), std::make_unique<L2capDynamicChannelHelper>(this, l2cap_layer_, facade_handler_, request->psm(),
                                                                    request->retransmission_mode()));
    return ::grpc::Status::OK;
  }

  ::grpc::Status SetTrafficPaused(::grpc::ServerContext* context, const SetTrafficPausedRequest* request,
                                  ::google::protobuf::Empty* response) override {
    auto psm = request->psm();
    if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) {
      return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
    }
    if (request->paused()) {
      dynamic_channel_helper_map_[psm]->SuspendDequeue();
    } else {
      dynamic_channel_helper_map_[psm]->ResumeDequeue();
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status GetChannelQueueDepth(::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
                                      GetChannelQueueDepthResponse* response) override {
    // Use the value kChannelQueueSize (5) in internal/dynamic_channel_impl.h
    response->set_size(5);
    return ::grpc::Status::OK;
  }

  ::grpc::Status InitiateConnectionForSecurity(
      ::grpc::ServerContext* context,
      const facade::BluetoothAddress* request,
      ::google::protobuf::Empty* response) override {
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->address(), peer));
    outgoing_pairing_remote_devices_.insert(peer);
    security_interface_->InitiateConnectionForSecurity(peer);
    return ::grpc::Status::OK;
  }

  void SecurityConnectionEventOccurred(
      hci::ErrorCode hci_status, hci::Address remote, LinkSecurityInterfaceCallbackEventType event_type) {
    LinkSecurityInterfaceCallbackEvent msg;
    msg.mutable_address()->set_address(remote.ToString());
    msg.set_event_type(event_type);
    security_connection_events_.OnIncomingEvent(msg);
  }

  ::grpc::Status FetchSecurityConnectionEvents(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::grpc::ServerWriter<LinkSecurityInterfaceCallbackEvent>* writer) override {
    security_interface_ = l2cap_layer_->GetSecurityInterface(facade_handler_, this);
    return security_connection_events_.RunLoop(context, writer);
  }

  ::grpc::Status SecurityLinkHold(
      ::grpc::ServerContext* context,
      const facade::BluetoothAddress* request,
      ::google::protobuf::Empty* response) override {
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->address(), peer));
    auto entry = security_link_map_.find(peer);
    if (entry == security_link_map_.end()) {
      LOG_WARN("Unknown address '%s'", peer.ToString().c_str());
    } else {
      entry->second->Hold();
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status SecurityLinkEnsureAuthenticated(
      ::grpc::ServerContext* context,
      const facade::BluetoothAddress* request,
      ::google::protobuf::Empty* response) override {
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->address(), peer));
    auto entry = security_link_map_.find(peer);
    if (entry == security_link_map_.end()) {
      LOG_WARN("Unknown address '%s'", peer.ToString().c_str());
    } else {
      entry->second->EnsureAuthenticated();
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status SecurityLinkRelease(
      ::grpc::ServerContext* context,
      const facade::BluetoothAddress* request,
      ::google::protobuf::Empty* response) override {
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->address(), peer));
    outgoing_pairing_remote_devices_.erase(peer);
    auto entry = security_link_map_.find(peer);
    if (entry == security_link_map_.end()) {
      LOG_WARN("Unknown address '%s'", peer.ToString().c_str());
    } else {
      entry->second->Release();
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status SecurityLinkDisconnect(
      ::grpc::ServerContext* context,
      const facade::BluetoothAddress* request,
      ::google::protobuf::Empty* response) override {
    hci::Address peer;
    ASSERT(hci::Address::FromString(request->address(), peer));
    outgoing_pairing_remote_devices_.erase(peer);
    auto entry = security_link_map_.find(peer);
    if (entry == security_link_map_.end()) {
      LOG_WARN("Unknown address '%s'", peer.ToString().c_str());
    } else {
      entry->second->Disconnect();
    }
    return ::grpc::Status::OK;
  }

  void OnLinkConnected(std::unique_ptr<LinkSecurityInterface> link) override {
    auto remote = link->GetRemoteAddress();
    if (outgoing_pairing_remote_devices_.count(remote) == 1) {
      link->Hold();
      link->EnsureAuthenticated();
      outgoing_pairing_remote_devices_.erase(remote);
    }
    security_link_map_.emplace(remote, std::move(link));
    SecurityConnectionEventOccurred(
        hci::ErrorCode::SUCCESS, remote, LinkSecurityInterfaceCallbackEventType::ON_CONNECTED);
  }

  void OnLinkDisconnected(hci::Address remote) override {
    auto entry = security_link_map_.find(remote);
    if (entry == security_link_map_.end()) {
      LOG_WARN("Unknown address '%s'", remote.ToString().c_str());
      return;
    }
    entry->second.reset();
    security_link_map_.erase(entry);
    SecurityConnectionEventOccurred(
        hci::ErrorCode::SUCCESS, remote, LinkSecurityInterfaceCallbackEventType::ON_DISCONNECTED);
  }

  void OnAuthenticationComplete(hci::ErrorCode hci_status, hci::Address remote) override {
    auto entry = security_link_map_.find(remote);
    if (entry != security_link_map_.end()) {
      entry->second->EnsureEncrypted();
      return;
    }
    SecurityConnectionEventOccurred(
        hci_status, remote, LinkSecurityInterfaceCallbackEventType::ON_AUTHENTICATION_COMPLETE);
  }

  void OnEncryptionChange(hci::Address remote, bool encrypted) override {
    SecurityConnectionEventOccurred(
        hci::ErrorCode::SUCCESS, remote, LinkSecurityInterfaceCallbackEventType::ON_ENCRYPTION_CHANGE);
  }

  class L2capDynamicChannelHelper {
   public:
    L2capDynamicChannelHelper(L2capClassicModuleFacadeService* service, L2capClassicModule* l2cap_layer,
                              os::Handler* handler, Psm psm, RetransmissionFlowControlMode mode)
        : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm), mode_(mode) {
      dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager();
      DynamicChannelConfigurationOption configuration_option = {};
      configuration_option.channel_mode = (DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode)mode;
      dynamic_channel_manager_->RegisterService(
          psm,
          configuration_option,
          SecurityPolicy::_SDP_ONLY_NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK,
          handler_->BindOnceOn(this, &L2capDynamicChannelHelper::on_l2cap_service_registration_complete),
          handler_->BindOn(this, &L2capDynamicChannelHelper::on_connection_open));
    }

    ~L2capDynamicChannelHelper() {
      if (dequeue_registered_) {
        channel_->GetQueueUpEnd()->UnregisterDequeue();
        channel_ = nullptr;
      }
      enqueue_buffer_.reset();
    }

    void Connect(hci::Address address) {
      DynamicChannelConfigurationOption configuration_option = l2cap::classic::DynamicChannelConfigurationOption();
      configuration_option.channel_mode = (DynamicChannelConfigurationOption::RetransmissionAndFlowControlMode)mode_;

      dynamic_channel_manager_->ConnectChannel(
          address,
          configuration_option,
          psm_,
          handler_->BindOn(this, &L2capDynamicChannelHelper::on_connection_open),
          handler_->BindOnceOn(this, &L2capDynamicChannelHelper::on_connect_fail));
      std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
      if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), [this] { return channel_ != nullptr; })) {
        LOG_WARN("Channel is not open for psm %d", psm_);
      }
    }

    void Disconnect() {
      if (channel_ == nullptr) {
        std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
        if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), [this] { return channel_ != nullptr; })) {
          LOG_WARN("Channel is not open for psm %d", psm_);
          return;
        }
      }
      channel_->Close();
    }

    void on_l2cap_service_registration_complete(DynamicChannelManager::RegistrationResult registration_result,
                                                std::unique_ptr<DynamicChannelService> service) {}

    // invoked from Facade Handler
    void on_connection_open(std::unique_ptr<DynamicChannel> channel) {
      ConnectionCompleteEvent event;
      event.mutable_remote()->set_address(channel->GetDevice().GetAddress().ToString());
      facade_service_->pending_connection_complete_.OnIncomingEvent(event);
      {
        std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
        channel_ = std::move(channel);
        enqueue_buffer_ = std::make_unique<os::EnqueueBuffer<BasePacketBuilder>>(channel_->GetQueueUpEnd());
      }
      channel_open_cv_.notify_all();
      channel_->RegisterOnCloseCallback(
          facade_service_->facade_handler_->BindOnceOn(this, &L2capDynamicChannelHelper::on_close_callback));
      dequeue_registered_ = true;
      channel_->GetQueueUpEnd()->RegisterDequeue(
          facade_service_->facade_handler_,
          common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, common::Unretained(this)));
    }

    void on_close_callback(hci::ErrorCode error_code) {
      {
        std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
        if (dequeue_registered_.exchange(false)) {
          channel_->GetQueueUpEnd()->UnregisterDequeue();
        }
      }
      classic::ConnectionCloseEvent event;
      event.mutable_remote()->set_address(channel_->GetDevice().GetAddress().ToString());
      event.set_reason(static_cast<uint32_t>(error_code));
      facade_service_->pending_connection_close_.OnIncomingEvent(event);
      channel_ = nullptr;
      enqueue_buffer_.reset();
    }

    void SuspendDequeue() {
      if (dequeue_registered_.exchange(false)) {
        channel_->GetQueueUpEnd()->UnregisterDequeue();
      }
    }

    void ResumeDequeue() {
      if (!dequeue_registered_.exchange(true)) {
        channel_->GetQueueUpEnd()->RegisterDequeue(
            facade_service_->facade_handler_,
            common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, common::Unretained(this)));
      }
    }

    void on_connect_fail(DynamicChannelManager::ConnectionResult result) {}

    void on_incoming_packet() {
      auto packet = channel_->GetQueueUpEnd()->TryDequeue();
      std::string data = std::string(packet->begin(), packet->end());
      L2capPacket l2cap_data;
      l2cap_data.set_psm(psm_);
      l2cap_data.set_payload(data);
      facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data);
    }

    bool SendPacket(std::vector<uint8_t> packet) {
      if (channel_ == nullptr) {
        std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
        if (!channel_open_cv_.wait_for(lock, std::chrono::seconds(2), [this] { return channel_ != nullptr; })) {
          LOG_WARN("Channel is not open");
          return false;
        }
      }
      auto packet_one = std::make_unique<packet::RawBuilder>(2000);
      packet_one->AddOctets(packet);
      enqueue_buffer_->Enqueue(std::move(packet_one), handler_);
      return true;
    }
    L2capClassicModuleFacadeService* facade_service_;
    L2capClassicModule* l2cap_layer_;
    os::Handler* handler_;
    std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_;
    std::unique_ptr<DynamicChannelService> service_;
    std::unique_ptr<DynamicChannel> channel_ = nullptr;
    std::unique_ptr<os::EnqueueBuffer<BasePacketBuilder>> enqueue_buffer_ = nullptr;
    Psm psm_;
    RetransmissionFlowControlMode mode_ = RetransmissionFlowControlMode::BASIC;
    std::atomic_bool dequeue_registered_ = false;
    std::condition_variable channel_open_cv_;
    std::mutex channel_open_cv_mutex_;
  };

  L2capClassicModule* l2cap_layer_;
  ::bluetooth::os::Handler* facade_handler_;
  std::mutex channel_map_mutex_;
  std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_;
  ::bluetooth::grpc::GrpcEventQueue<classic::ConnectionCompleteEvent> pending_connection_complete_{
      "FetchConnectionComplete"};
  ::bluetooth::grpc::GrpcEventQueue<classic::ConnectionCloseEvent> pending_connection_close_{"FetchConnectionClose"};
  ::bluetooth::grpc::GrpcEventQueue<L2capPacket> pending_l2cap_data_{"FetchL2capData"};
  ::bluetooth::grpc::GrpcEventQueue<LinkSecurityInterfaceCallbackEvent> security_connection_events_{
      "Security Connection Events"};
  SecurityInterface* security_interface_;
  std::unordered_map<hci::Address, std::unique_ptr<l2cap::classic::LinkSecurityInterface>> security_link_map_;
  std::set<hci::Address> outgoing_pairing_remote_devices_;
};

void L2capClassicModuleFacadeModule::ListDependencies(ModuleList* list) const {
  ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
  list->add<l2cap::classic::L2capClassicModule>();
}

void L2capClassicModuleFacadeModule::Start() {
  ::bluetooth::grpc::GrpcFacadeModule::Start();
  service_ = new L2capClassicModuleFacadeService(GetDependency<l2cap::classic::L2capClassicModule>(), GetHandler());
}

void L2capClassicModuleFacadeModule::Stop() {
  delete service_;
  ::bluetooth::grpc::GrpcFacadeModule::Stop();
}

::grpc::Service* L2capClassicModuleFacadeModule::GetService() const {
  return service_;
}

const ModuleFactory L2capClassicModuleFacadeModule::Factory =
    ::bluetooth::ModuleFactory([]() { return new L2capClassicModuleFacadeModule(); });

}  // namespace classic
}  // namespace l2cap
}  // namespace bluetooth
