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

#include <string>

#include "facade/read_only_property_server.h"
#include "facade/rootservice.grpc.pb.h"
#include "grpc/grpc_module.h"
#include "hal/facade.h"
#include "hci/facade.h"
#include "l2cap/classic/facade.h"
#include "os/log.h"
#include "os/thread.h"
#include "stack_manager.h"

namespace bluetooth {
namespace facade {

using ::bluetooth::grpc::GrpcModule;
using ::bluetooth::os::Thread;

namespace {
class RootFacadeService : public ::bluetooth::facade::RootFacade::Service {
 public:
  RootFacadeService(int grpc_port) : grpc_port_(grpc_port) {}

  ::grpc::Status StartStack(::grpc::ServerContext* context, const ::bluetooth::facade::StartStackRequest* request,
                            ::bluetooth::facade::StartStackResponse* response) override {
    if (is_running_) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is running");
    }

    ModuleList modules;
    modules.add<::bluetooth::grpc::GrpcModule>();

    BluetoothModule module_under_test = request->module_under_test();
    switch (module_under_test) {
      case BluetoothModule::HAL:
        modules.add<::bluetooth::hal::HciHalFacadeModule>();
        break;
      case BluetoothModule::HCI:
        modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
        modules.add<::bluetooth::hci::AclManagerFacadeModule>();
        modules.add<::bluetooth::hci::ClassicSecurityManagerFacadeModule>();
        break;
      case BluetoothModule::L2CAP:
        modules.add<::bluetooth::facade::ReadOnlyPropertyServerModule>();
        modules.add<::bluetooth::l2cap::classic::L2capClassicModuleFacadeModule>();
        break;
      default:
        return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "invalid module under test");
    }

    stack_thread_ = new Thread("stack_thread", Thread::Priority::NORMAL);
    stack_manager_.StartUp(&modules, stack_thread_);

    GrpcModule* grpc_module = stack_manager_.GetInstance<GrpcModule>();
    grpc_module->StartServer("0.0.0.0", grpc_port_);

    grpc_loop_thread_ = new std::thread([grpc_module] { grpc_module->RunGrpcLoop(); });
    is_running_ = true;

    return ::grpc::Status::OK;
  }

  ::grpc::Status StopStack(::grpc::ServerContext* context, const ::bluetooth::facade::StopStackRequest* request,
                           ::bluetooth::facade::StopStackResponse* response) override {
    if (!is_running_) {
      return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "stack is not running");
    }

    stack_manager_.GetInstance<GrpcModule>()->StopServer();
    grpc_loop_thread_->join();
    delete grpc_loop_thread_;

    stack_manager_.ShutDown();
    delete stack_thread_;
    is_running_ = false;
    return ::grpc::Status::OK;
  }

 private:
  Thread* stack_thread_ = nullptr;
  bool is_running_ = false;
  std::thread* grpc_loop_thread_ = nullptr;
  StackManager stack_manager_;
  int grpc_port_ = 8898;
};

RootFacadeService* root_facade_service;
}  // namespace

void GrpcRootServer::StartServer(const std::string& address, int grpc_root_server_port, int grpc_port) {
  ASSERT(!started_);
  started_ = true;

  std::string listening_port = address + ":" + std::to_string(grpc_root_server_port);
  ::grpc::ServerBuilder builder;
  root_facade_service = new RootFacadeService(grpc_port);
  builder.RegisterService(root_facade_service);
  builder.AddListeningPort(listening_port, ::grpc::InsecureServerCredentials());
  server_ = builder.BuildAndStart();

  ASSERT(server_ != nullptr);
}

void GrpcRootServer::StopServer() {
  ASSERT(started_);
  server_->Shutdown();
  started_ = false;
  server_.reset();
  delete root_facade_service;
}

void GrpcRootServer::RunGrpcLoop() {
  ASSERT(started_);
  server_->Wait();
}

}  // namespace facade
}  // namespace bluetooth
