/*
 * 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 "hci/facade/facade.h"

#include <memory>

#include "common/bind.h"
#include "grpc/grpc_event_queue.h"
#include "hci/controller.h"
#include "hci/facade/hci_facade.grpc.pb.h"
#include "hci/hci_layer.h"
#include "hci/hci_packets.h"

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

namespace bluetooth {
namespace hci {
namespace facade {

class HciFacadeService : public HciFacade::Service {
 public:
  HciFacadeService(HciLayer* hci_layer, Controller* controller, ::bluetooth::os::Handler* facade_handler)
      : hci_layer_(hci_layer), controller_(controller), facade_handler_(facade_handler) {}

  virtual ~HciFacadeService() {
    if (unregister_acl_dequeue_) {
      hci_layer_->GetAclQueueEnd()->UnregisterDequeue();
    }
    if (waiting_acl_packet_ != nullptr) {
      hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
      if (waiting_acl_packet_ != nullptr) {
        waiting_acl_packet_.reset();
      }
    }
  }

  class TestCommandBuilder : public CommandBuilder {
   public:
    explicit TestCommandBuilder(std::vector<uint8_t> bytes) : CommandBuilder(OpCode::NONE), bytes_(std::move(bytes)) {}
    size_t size() const override {
      return bytes_.size();
    }
    void Serialize(BitInserter& bit_inserter) const override {
      for (auto&& b : bytes_) {
        bit_inserter.insert_byte(b);
      }
    }

   private:
    std::vector<uint8_t> bytes_;
  };

  ::grpc::Status SendCommand(
      ::grpc::ServerContext* context,
      const ::bluetooth::facade::Data* command,
      ::google::protobuf::Empty* response) override {
    auto payload = std::vector<uint8_t>(command->payload().begin(), command->payload().end());
    auto packet = std::make_unique<TestCommandBuilder>(payload);
    auto opcode = static_cast<const bluetooth::hci::OpCode>(payload.at(1) << 8 | payload.at(0));
    if (Checker::IsCommandStatusOpcode(opcode)) {
      hci_layer_->EnqueueCommand(std::move(packet), facade_handler_->BindOnceOn(this, &HciFacadeService::on_status));
    } else {
      hci_layer_->EnqueueCommand(std::move(packet), facade_handler_->BindOnceOn(this, &HciFacadeService::on_complete));
    }
    return ::grpc::Status::OK;
  }

  ::grpc::Status RequestEvent(
      ::grpc::ServerContext* context,
      const ::bluetooth::hci::EventRequest* event,
      ::google::protobuf::Empty* response) override {
    hci_layer_->RegisterEventHandler(
        static_cast<EventCode>(event->code()), facade_handler_->BindOn(this, &HciFacadeService::on_event));
    return ::grpc::Status::OK;
  }

  ::grpc::Status RequestLeSubevent(
      ::grpc::ServerContext* context,
      const ::bluetooth::hci::EventRequest* event,
      ::google::protobuf::Empty* response) override {
    hci_layer_->RegisterLeEventHandler(
        static_cast<SubeventCode>(event->code()), facade_handler_->BindOn(this, &HciFacadeService::on_le_subevent));
    return ::grpc::Status::OK;
  }

  ::grpc::Status StreamEvents(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::grpc::ServerWriter<::bluetooth::facade::Data>* writer) override {
    return pending_events_.RunLoop(context, writer);
  };

  ::grpc::Status StreamLeSubevents(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::grpc::ServerWriter<::bluetooth::facade::Data>* writer) override {
    return pending_le_events_.RunLoop(context, writer);
  };

  class TestAclBuilder : public AclBuilder {
   public:
    explicit TestAclBuilder(std::vector<uint8_t> payload)
        : AclBuilder(0xbad, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::ACTIVE_PERIPHERAL_BROADCAST),
          bytes_(std::move(payload)) {}

    size_t size() const override {
      return bytes_.size();
    }
    void Serialize(BitInserter& bit_inserter) const override {
      for (auto&& b : bytes_) {
        bit_inserter.insert_byte(b);
      }
    }

   private:
    std::vector<uint8_t> bytes_;
  };

  ::grpc::Status SendAcl(
      ::grpc::ServerContext* context,
      const ::bluetooth::facade::Data* acl,
      ::google::protobuf::Empty* response) override {
    waiting_acl_packet_ =
        std::make_unique<TestAclBuilder>(std::vector<uint8_t>(acl->payload().begin(), acl->payload().end()));
    std::promise<void> enqueued;
    auto future = enqueued.get_future();
    if (!completed_packets_callback_registered_) {
      controller_->RegisterCompletedAclPacketsCallback(
          facade_handler_->Bind([](uint16_t, uint16_t) { /* do nothing */ }));
      completed_packets_callback_registered_ = true;
    }
    hci_layer_->GetAclQueueEnd()->RegisterEnqueue(
        facade_handler_,
        common::Bind(&HciFacadeService::handle_enqueue_acl, common::Unretained(this), common::Unretained(&enqueued)));
    auto result = future.wait_for(std::chrono::milliseconds(100));
    ASSERT(std::future_status::ready == result);
    return ::grpc::Status::OK;
  }

  ::grpc::Status StreamAcl(
      ::grpc::ServerContext* context,
      const ::google::protobuf::Empty* request,
      ::grpc::ServerWriter<::bluetooth::facade::Data>* writer) override {
    hci_layer_->GetAclQueueEnd()->RegisterDequeue(
        facade_handler_, common::Bind(&HciFacadeService::on_acl_ready, common::Unretained(this)));
    unregister_acl_dequeue_ = true;
    return pending_acl_events_.RunLoop(context, writer);
  };

 private:
  std::unique_ptr<AclBuilder> handle_enqueue_acl(std::promise<void>* promise) {
    promise->set_value();
    hci_layer_->GetAclQueueEnd()->UnregisterEnqueue();
    return std::move(waiting_acl_packet_);
  }

  void on_acl_ready() {
    auto acl_ptr = hci_layer_->GetAclQueueEnd()->TryDequeue();
    ASSERT(acl_ptr != nullptr);
    ASSERT(acl_ptr->IsValid());
    LOG_INFO("Got an Acl message for handle 0x%hx", acl_ptr->GetHandle());
    ::bluetooth::facade::Data incoming;
    incoming.set_payload(std::string(acl_ptr->begin(), acl_ptr->end()));
    pending_acl_events_.OnIncomingEvent(std::move(incoming));
  }

  void on_event(hci::EventView view) {
    ASSERT(view.IsValid());
    LOG_INFO("Got an Event %s", EventCodeText(view.GetEventCode()).c_str());
    ::bluetooth::facade::Data response;
    response.set_payload(std::string(view.begin(), view.end()));
    pending_events_.OnIncomingEvent(std::move(response));
  }

  void on_le_subevent(hci::LeMetaEventView view) {
    ASSERT(view.IsValid());
    LOG_INFO("Got an LE Event %s", SubeventCodeText(view.GetSubeventCode()).c_str());
    ::bluetooth::facade::Data response;
    response.set_payload(std::string(view.begin(), view.end()));
    pending_le_events_.OnIncomingEvent(std::move(response));
  }

  void on_complete(hci::CommandCompleteView view) {
    ASSERT(view.IsValid());
    LOG_INFO("Got a Command complete %s", OpCodeText(view.GetCommandOpCode()).c_str());
    ::bluetooth::facade::Data response;
    response.set_payload(std::string(view.begin(), view.end()));
    pending_events_.OnIncomingEvent(std::move(response));
  }

  void on_status(hci::CommandStatusView view) {
    ASSERT(view.IsValid());
    LOG_INFO("Got a Command status %s", OpCodeText(view.GetCommandOpCode()).c_str());
    ::bluetooth::facade::Data response;
    response.set_payload(std::string(view.begin(), view.end()));
    pending_events_.OnIncomingEvent(std::move(response));
  }

  HciLayer* hci_layer_;
  Controller* controller_;
  ::bluetooth::os::Handler* facade_handler_;
  ::bluetooth::grpc::GrpcEventQueue<::bluetooth::facade::Data> pending_events_{"StreamEvents"};
  ::bluetooth::grpc::GrpcEventQueue<::bluetooth::facade::Data> pending_le_events_{"StreamLeSubevents"};
  ::bluetooth::grpc::GrpcEventQueue<::bluetooth::facade::Data> pending_acl_events_{"StreamAcl"};
  bool unregister_acl_dequeue_{false};
  std::unique_ptr<TestAclBuilder> waiting_acl_packet_;
  bool completed_packets_callback_registered_{false};
};

void HciFacadeModule::ListDependencies(ModuleList* list) {
  ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
  list->add<HciLayer>();
  list->add<Controller>();
}

void HciFacadeModule::Start() {
  ::bluetooth::grpc::GrpcFacadeModule::Start();
  service_ = new HciFacadeService(GetDependency<HciLayer>(), GetDependency<Controller>(), GetHandler());
}

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

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

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

}  // namespace facade
}  // namespace hci
}  // namespace bluetooth
