/*
 * Copyright (C) 2017 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 "mcap_test_app.h"
#include "mca_defs.h"

namespace SYSTEM_BT_TOOLS_MCAP_TOOL {

#define CASE_RETURN_STR(const) \
  case const:                  \
    return #const;

static const char* dump_mcap_events(const uint8_t event) {
  switch (event) {
    CASE_RETURN_STR(MCA_ERROR_RSP_EVT)
    CASE_RETURN_STR(MCA_CREATE_IND_EVT)
    CASE_RETURN_STR(MCA_CREATE_CFM_EVT)
    CASE_RETURN_STR(MCA_RECONNECT_IND_EVT)
    CASE_RETURN_STR(MCA_RECONNECT_CFM_EVT)
    CASE_RETURN_STR(MCA_ABORT_IND_EVT)
    CASE_RETURN_STR(MCA_ABORT_CFM_EVT)
    CASE_RETURN_STR(MCA_DELETE_IND_EVT)
    CASE_RETURN_STR(MCA_DELETE_CFM_EVT)
    CASE_RETURN_STR(MCA_SYNC_CAP_IND_EVT)
    CASE_RETURN_STR(MCA_SYNC_CAP_CFM_EVT)
    CASE_RETURN_STR(MCA_SYNC_SET_IND_EVT)
    CASE_RETURN_STR(MCA_SYNC_SET_CFM_EVT)
    CASE_RETURN_STR(MCA_SYNC_INFO_IND_EVT)
    CASE_RETURN_STR(MCA_CONNECT_IND_EVT)
    CASE_RETURN_STR(MCA_DISCONNECT_IND_EVT)
    CASE_RETURN_STR(MCA_OPEN_IND_EVT)
    CASE_RETURN_STR(MCA_OPEN_CFM_EVT)
    CASE_RETURN_STR(MCA_CLOSE_IND_EVT)
    CASE_RETURN_STR(MCA_CLOSE_CFM_EVT)
    CASE_RETURN_STR(MCA_CONG_CHG_EVT)
    CASE_RETURN_STR(MCA_RSP_TOUT_IND_EVT)
    default:
      return "Unknown event";
  }
}

static void print_mcap_event(const tMCA_DISCONNECT_IND* mcap_disconnect_ind) {
  printf("%s: peer_bd_addr=%s,l2cap_disconnect_reason=0x%04x\n", __func__,
         mcap_disconnect_ind->bd_addr.ToString().c_str(),
         mcap_disconnect_ind->reason);
}

static void print_mcap_event(const tMCA_CONNECT_IND* mcap_connect_ind) {
  printf("%s: peer_bd_addr=%s, peer_mtu=%d \n", __func__,
         mcap_connect_ind->bd_addr.ToString().c_str(), mcap_connect_ind->mtu);
}

static void print_mcap_event(const tMCA_RSP_EVT* mcap_rsp) {
  printf("%s: response, mdl_id=%d, op_code=0x%02x, rsp_code=0x%02x\n", __func__,
         mcap_rsp->mdl_id, mcap_rsp->op_code, mcap_rsp->rsp_code);
}

static void print_mcap_event(const tMCA_EVT_HDR* mcap_evt_hdr) {
  printf("%s: event, mdl_id=%d, op_code=0x%02x\n", __func__,
         mcap_evt_hdr->mdl_id, mcap_evt_hdr->op_code);
}

static void print_mcap_event(const tMCA_CREATE_IND* mcap_create_ind) {
  printf("%s: mdl_id=%d, op_code=0x%02x, dep_id=%d, cfg=0x%02x\n", __func__,
         mcap_create_ind->mdl_id, mcap_create_ind->op_code,
         mcap_create_ind->dep_id, mcap_create_ind->cfg);
}

static void print_mcap_event(const tMCA_CREATE_CFM* mcap_create_cfm) {
  printf("%s: mdl_id=%d, op_code=0x%02x, rsp_code=%d, cfg=0x%02x\n", __func__,
         mcap_create_cfm->mdl_id, mcap_create_cfm->op_code,
         mcap_create_cfm->rsp_code, mcap_create_cfm->cfg);
}

static void print_mcap_event(const tMCA_DL_OPEN* mcap_dl_open) {
  printf("%s: mdl_id=%d, mdl_handle=%d, mtu=%d\n", __func__,
         mcap_dl_open->mdl_id, mcap_dl_open->mdl, mcap_dl_open->mtu);
}

static void print_mcap_event(const tMCA_DL_CLOSE* mcap_dl_close) {
  printf("%s: mdl_id=%d, mdl_handle=%d, l2cap_disconnect_reason=0x%04x\n",
         __func__, mcap_dl_close->mdl_id, mcap_dl_close->mdl,
         mcap_dl_close->reason);
}

static void print_mcap_event(const tMCA_CONG_CHG* mcap_congestion_change) {
  printf("%s: mdl_id=%d, mdl_handle=%d, congested=%d\n", __func__,
         mcap_congestion_change->mdl_id, mcap_congestion_change->mdl,
         mcap_congestion_change->cong);
}

McapTestApp::McapTestApp(btmcap_test_interface_t* mcap_test_interface)
    : _mcl_list(), _mdep_list() {
  _mcap_test_interface = mcap_test_interface;
}

btmcap_test_interface_t* McapTestApp::GetInterface() {
  return _mcap_test_interface;
}

bool McapTestApp::Register(uint16_t ctrl_psm, uint16_t data_psm,
                           uint16_t sec_mask, tMCA_CTRL_CBACK* callback) {
  if (!callback) {
    LOG(ERROR) << "callback is null";
    return false;
  }
  _mca_reg.rsp_tout = 5000;
  _mca_reg.ctrl_psm = ctrl_psm;
  _mca_reg.data_psm = data_psm;
  _mca_reg.sec_mask = sec_mask;
  _mcap_handle =
      _mcap_test_interface->register_application(&_mca_reg, callback);
  return _mcap_handle > 0;
}

void McapTestApp::Deregister() {
  _mcap_test_interface->deregister_application(_mcap_handle);
  _mcap_handle = 0;
}

bool McapTestApp::Registered() { return _mcap_handle > 0; }

bool McapTestApp::ConnectMcl(const RawAddress& bd_addr, uint16_t ctrl_psm,
                             uint16_t sec_mask) {
  if (!Registered()) {
    LOG(ERROR) << "Application not registered";
    return false;
  }
  McapMcl* mcap_mcl = FindMclByPeerAddress(bd_addr);
  if (!mcap_mcl) {
    LOG(INFO) << "MCL does not exist, creating new MCL";
    _mcl_list.push_back(McapMcl(_mcap_test_interface, _mcap_handle, bd_addr));
    mcap_mcl = &_mcl_list[_mcl_list.size() - 1];
  }
  if (mcap_mcl->GetHandle() != 0) {
    LOG(ERROR) << "MCL is still active, cannot make another connection";
    return false;
  }
  return mcap_mcl->Connect(ctrl_psm, sec_mask);
}

bool McapTestApp::CreateMdep(uint8_t type, uint8_t max_mdl,
                             tMCA_DATA_CBACK* data_callback) {
  if (!data_callback) {
    LOG(ERROR) << "Data callback is null";
    return false;
  }
  _mdep_list.push_back(McapMdep(_mcap_test_interface, _mcap_handle, type,
                                max_mdl, data_callback));
  return _mdep_list[_mdep_list.size() - 1].Create();
}

uint8_t McapTestApp::GetHandle() { return _mcap_handle; }

McapMcl* McapTestApp::FindMclByPeerAddress(const RawAddress& bd_addr) {
  for (McapMcl& mcl : _mcl_list) {
    if (mcl.GetPeerAddress() == bd_addr) {
      return &mcl;
    }
  }
  return nullptr;
}

McapMcl* McapTestApp::FindMclByHandle(tMCA_CL mcl_handle) {
  for (McapMcl& mcl : _mcl_list) {
    if (mcl.GetHandle() == mcl_handle) {
      return &mcl;
    }
  }
  return nullptr;
}

McapMdep* McapTestApp::FindMdepByHandle(tMCA_DEP mdep_handle) {
  for (McapMdep& mdep : _mdep_list) {
    if (mdep.GetHandle() == mdep_handle) {
      return &mdep;
    }
  }
  return nullptr;
}

void McapTestApp::RemoveMclByHandle(tMCA_CL mcl_handle) {
  LOG(INFO) << "Removing MCL handle " << (int)mcl_handle;
  for (std::vector<McapMcl>::iterator it = _mcl_list.begin();
       it != _mcl_list.end(); ++it) {
    if (it->GetHandle() == mcl_handle) {
      _mcl_list.erase(it);
      LOG(INFO) << "Removed MCL handle " << (int)mcl_handle;
      return;
    }
  }
}

bool McapTestApp::IsRegistered() { return _mcap_handle > 0; }

void McapTestApp::ControlCallback(tMCA_HANDLE handle, tMCA_CL mcl,
                                  uint8_t event, tMCA_CTRL* p_data) {
  McapMcl* mcap_mcl = FindMclByHandle(mcl);
  McapMdl* mcap_mdl = nullptr;
  printf("%s: mcap_handle=%d, mcl_handle=%d, event=%s (0x%02x)\n", __func__,
         handle, mcl, dump_mcap_events(event), event);
  if (_mcap_handle != handle) {
    LOG(ERROR) << "MCAP handle mismatch, self=" << _mcap_handle
               << ", other=" << handle;
    return;
  }
  switch (event) {
    case MCA_ERROR_RSP_EVT:
      print_mcap_event(&p_data->rsp);
      break;

    case MCA_CREATE_CFM_EVT:
      // Called when MCA_CreateMdl succeeded step 1 when response is received
      print_mcap_event(&p_data->create_cfm);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->create_cfm.mdl_id);
      if (!mcap_mdl) {
        LOG(ERROR) << "MDL not found for id " << p_data->create_cfm.mdl_id;
        break;
      }
      if (mcap_mdl->GetResponseCode() >= 0) {
        LOG(ERROR) << "MDL already got response " << mcap_mdl->GetResponseCode()
                   << " for id " << p_data->create_cfm.mdl_id;
        break;
      }
      mcap_mdl->SetResponseCode(p_data->create_cfm.rsp_code);
      break;

    case MCA_CREATE_IND_EVT: {
      // Should be replied with MCA_CreateMdlRsp
      print_mcap_event(&p_data->create_ind);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      McapMdep* mcap_mdep = FindMdepByHandle(p_data->create_ind.dep_id);
      if (!mcap_mdep) {
        LOG(ERROR) << "MDEP ID " << (int)p_data->create_ind.dep_id
                   << " does not exist";
        _mcap_test_interface->create_mdl_response(
            mcl, p_data->create_ind.dep_id, p_data->create_ind.mdl_id, 0,
            MCA_RSP_BAD_MDEP, get_test_channel_config());
        break;
      }
      bool ret = mcap_mcl->CreateMdlResponse(
          mcap_mdep->GetHandle(), p_data->create_ind.mdl_id,
          p_data->create_ind.dep_id, p_data->create_ind.cfg);
      LOG(INFO) << (ret ? "SUCCESS" : "FAIL");
      if (!ret) {
        _mcap_test_interface->create_mdl_response(
            mcl, p_data->create_ind.dep_id, p_data->create_ind.mdl_id, 0,
            MCA_RSP_NO_RESOURCE, get_test_channel_config());
      }
      break;
    }
    case MCA_RECONNECT_IND_EVT: {
      // Called when remote device asks to reconnect
      // reply with MCA_ReconnectMdlRsp
      print_mcap_event(&p_data->reconnect_ind);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->reconnect_ind.mdl_id);
      if (mcap_mdl && !mcap_mdl->IsConnected()) {
        LOG(INFO) << "Creating reconnect response for MDL "
                  << (int)p_data->reconnect_ind.mdl_id;
        mcap_mdl->ReconnectResponse();
        break;
      }
      LOG_IF(WARNING, mcap_mdl && mcap_mdl->IsConnected())
          << "MDL ID " << (int)p_data->reconnect_ind.mdl_id
          << " is already connected";
      LOG_IF(WARNING, !mcap_mdl) << "No MDL for mdl_id "
                                 << p_data->reconnect_ind.mdl_id;
      tMCA_DEP mdep_handle = 0;
      if (_mdep_list.size() > 0) {
        mdep_handle = _mdep_list[0].GetHandle();
      } else {
        LOG(ERROR) << "Cannot find any available MDEP";
      }
      tMCA_RESULT ret = _mcap_test_interface->reconnect_mdl_response(
          mcl, mdep_handle, p_data->reconnect_ind.mdl_id, MCA_RSP_BAD_MDL,
          get_test_channel_config());
      LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << ret;
      break;
    }
    case MCA_RECONNECT_CFM_EVT:
      // Called when MCA_ReconnectMdl step 1, receives a response
      print_mcap_event(&p_data->reconnect_cfm);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->reconnect_cfm.mdl_id);
      if (!mcap_mdl) {
        LOG(ERROR) << "MDL not found for id " << p_data->reconnect_cfm.mdl_id;
        break;
      }
      if (mcap_mdl->GetResponseCode() >= 0) {
        LOG(ERROR) << "MDL already got response " << mcap_mdl->GetResponseCode()
                   << " for id " << p_data->reconnect_cfm.mdl_id;
        break;
      }
      mcap_mdl->SetResponseCode(p_data->reconnect_cfm.rsp_code);
      break;

    case MCA_ABORT_IND_EVT:
      print_mcap_event(&p_data->abort_ind);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->abort_ind.mdl_id);
      if (!mcap_mdl) {
        LOG(ERROR) << "MDL not found for id " << (int)p_data->abort_ind.mdl_id;
        break;
      }
      if (mcap_mdl->IsConnected()) {
        LOG(ERROR) << "MDL is already connected for id "
                   << (int)p_data->abort_ind.mdl_id;
      }
      mcap_mcl->RemoveMdl(p_data->abort_ind.mdl_id);
      break;

    case MCA_ABORT_CFM_EVT:
      // Called when MCA_Abort succeeded
      print_mcap_event(&p_data->abort_cfm);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->abort_cfm.mdl_id);
      if (!mcap_mdl) {
        LOG(ERROR) << "MDL not found for id " << (int)p_data->abort_cfm.mdl_id;
        break;
      }
      if (mcap_mdl->IsConnected()) {
        LOG(ERROR) << "MDL is already connected for id "
                   << (int)p_data->abort_cfm.mdl_id;
      }
      mcap_mcl->RemoveMdl(p_data->abort_cfm.mdl_id);
      break;

    case MCA_DELETE_IND_EVT:
      print_mcap_event(&p_data->delete_ind);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      if (p_data->delete_ind.mdl_id == MCA_ALL_MDL_ID) {
        mcap_mcl->RemoveAllMdl();
      } else {
        mcap_mcl->RemoveMdl(p_data->delete_ind.mdl_id);
      }
      break;

    case MCA_DELETE_CFM_EVT:
      // Called when MCA_Delete succeeded
      print_mcap_event(&p_data->delete_cfm);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
        break;
      }
      if (p_data->delete_cfm.rsp_code) {
        LOG(ERROR) << "No success response " << (int)p_data->delete_cfm.rsp_code
                   << " when deleting MDL_ID "
                   << (int)p_data->delete_cfm.mdl_id;
        break;
      }
      if (p_data->delete_cfm.mdl_id == MCA_ALL_MDL_ID) {
        mcap_mcl->RemoveAllMdl();
      } else {
        mcap_mcl->RemoveMdl(p_data->delete_cfm.mdl_id);
      }
      break;

    case MCA_CONNECT_IND_EVT: {
      // Called when MCA_ConnectReq succeeded
      print_mcap_event(&p_data->connect_ind);
      LOG(INFO) << "Received MCL handle " << (int)mcl;
      RawAddress bd_addr = p_data->connect_ind.bd_addr;
      mcap_mcl = FindMclByPeerAddress(bd_addr);
      if (!mcap_mcl) {
        LOG(INFO) << "Creating new MCL for ID " << (int)mcl;
        _mcl_list.push_back(
            McapMcl(_mcap_test_interface, _mcap_handle, bd_addr));
        mcap_mcl = &_mcl_list[_mcl_list.size() - 1];
      }
      if (mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL is already connected for handle " << (int)mcl;
        break;
      }
      mcap_mcl->SetHandle(mcl);
      mcap_mcl->SetMtu(p_data->connect_ind.mtu);
      break;
    }
    case MCA_DISCONNECT_IND_EVT: {
      // Called when MCA_ConnectReq failed or MCA_DisconnectReq succeeded
      print_mcap_event(&p_data->disconnect_ind);
      RawAddress bd_addr = p_data->disconnect_ind.bd_addr;
      mcap_mcl = FindMclByPeerAddress(bd_addr);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for BD addr " << bd_addr;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(WARNING) << "MCL for " << bd_addr << " is already disconnected";
      }
      mcap_mcl->SetHandle(0);
      mcap_mcl->SetMtu(0);
      mcap_mcl->ResetAllMdl();
      break;
    }
    case MCA_OPEN_IND_EVT:
    // Called when MCA_CreateMdlRsp succeeded step 2, data channel is open
    // Called when MCA_ReconnectMdlRsp succeeded step 2, data channel is open
    case MCA_OPEN_CFM_EVT:
      // Called when MCA_CreateMdl succeeded step 2, data channel is open
      // Called when MCA_ReconnectMdl succeeded step 2, data channel is open
      // Called when MCA_DataChnlCfg succeeded
      print_mcap_event(&p_data->open_ind);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->open_ind.mdl_id);
      if (mcap_mdl) {
        if (mcap_mdl->IsConnected()) {
          LOG(ERROR) << "MDL is already connected for mcl_handle "
                     << (int)p_data->open_ind.mdl_id;
          break;
        }
        mcap_mdl->SetMtu(p_data->open_ind.mtu);
        mcap_mdl->SetHandle(p_data->open_ind.mdl);
      } else {
        LOG(ERROR) << "No MDL for mdl_id " << (int)p_data->reconnect_ind.mdl_id;
      }
      break;

    case MCA_CLOSE_IND_EVT:
    case MCA_CLOSE_CFM_EVT:
      // Called when MCA_CloseReq is successful
      print_mcap_event(&p_data->close_cfm);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
        break;
      }
      mcap_mdl = mcap_mcl->FindMdlById(p_data->close_cfm.mdl_id);
      if (mcap_mdl) {
        mcap_mdl->SetMtu(0);
        mcap_mdl->SetHandle(0);
      } else {
        LOG(WARNING) << "No MDL for mdl_id " << (int)p_data->close_cfm.mdl_id;
      }
      break;

    case MCA_CONG_CHG_EVT:
      print_mcap_event(&p_data->cong_chg);
      if (!mcap_mcl) {
        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
        break;
      }
      if (!mcap_mcl->IsConnected()) {
        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
        break;
      }
      break;

    case MCA_RSP_TOUT_IND_EVT:
    case MCA_SYNC_CAP_IND_EVT:
    case MCA_SYNC_CAP_CFM_EVT:
    case MCA_SYNC_SET_IND_EVT:
    case MCA_SYNC_SET_CFM_EVT:
    case MCA_SYNC_INFO_IND_EVT:
      print_mcap_event(&p_data->hdr);
      break;
  }
}

}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
