// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "fake_gatt_server.h"

#include <endian.h>
#include <zircon/assert.h>

#include "fake_controller.h"
#include "fake_peer.h"
#include "src/connectivity/bluetooth/core/bt-host/att/packet.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt_defs.h"

namespace bt {
namespace testing {

FakeGattServer::FakeGattServer(FakePeer* dev) : dev_(dev) { ZX_DEBUG_ASSERT(dev_); }

void FakeGattServer::HandlePdu(hci::ConnectionHandle conn, const ByteBuffer& pdu) {
  if (pdu.size() < sizeof(att::OpCode)) {
    bt_log(WARN, "fake-hci", "malformed ATT packet!");
    return;
  }

  att::OpCode opcode = le16toh(pdu.As<att::OpCode>());
  switch (opcode) {
    case att::kExchangeMTURequest:
      // Always reply back with the default ATT_MTU.
      Send(conn, CreateStaticByteBuffer(att::kExchangeMTUResponse, att::kLEMinMTU, 0x00));
      break;
    case att::kReadByGroupTypeRequest:
      HandleReadByGrpType(conn, pdu.view(sizeof(att::OpCode)));
      break;
    default:
      SendErrorRsp(conn, opcode, 0, att::ErrorCode::kRequestNotSupported);
      break;
  }
}

void FakeGattServer::HandleReadByGrpType(hci::ConnectionHandle conn, const ByteBuffer& bytes) {
  // Don't support 128-bit group types.
  if (bytes.size() != sizeof(att::ReadByGroupTypeRequestParams16)) {
    SendErrorRsp(conn, att::kReadByGroupTypeRequest, 0, att::ErrorCode::kInvalidPDU);
    return;
  }

  const auto& params = bytes.As<att::ReadByGroupTypeRequestParams16>();
  att::Handle start = le16toh(params.start_handle);
  att::Handle end = le16toh(params.end_handle);
  if (!start || end < start) {
    SendErrorRsp(conn, att::kReadByGroupTypeRequest, start, att::ErrorCode::kInvalidHandle);
    return;
  }

  // Only support primary service discovery.
  uint16_t grp_type = le16toh(params.type);
  if (grp_type != gatt::types::kPrimaryService16 || start > 1) {
    SendErrorRsp(conn, att::kReadByGroupTypeRequest, start, att::ErrorCode::kAttributeNotFound);
    return;
  }

  // We report back the standard services.
  // TODO(armansito): Support standard characteristics and more services.
  auto rsp = CreateStaticByteBuffer(att::kReadByGroupTypeResponse,  // opcode
                                    6,                              // entry length
                                    0x01, 0x00,                     // start handle: 1
                                    0x01, 0x00,                     // end handle: 1
                                    0x00, 0x18,                     // "GAP Service" UUID: 0x1800
                                    0x02, 0x00,                     // start handle: 2
                                    0x02, 0x00,                     // end handle: 2
                                    0x01, 0x18                      // "GATT Service" UUID: 0x1801
  );
  Send(conn, rsp);
}

void FakeGattServer::Send(hci::ConnectionHandle conn, const ByteBuffer& pdu) {
  if (dev_->ctrl()) {
    dev_->ctrl()->SendL2CAPBFrame(conn, l2cap::kATTChannelId, pdu);
  } else {
    bt_log(WARN, "fake-hci", "no assigned FakeController!");
  }
}

void FakeGattServer::SendErrorRsp(hci::ConnectionHandle conn, att::OpCode opcode,
                                  att::Handle handle, att::ErrorCode ecode) {
  StaticByteBuffer<sizeof(att::ErrorResponseParams) + sizeof(att::OpCode)> buffer;
  att::PacketWriter writer(att::kErrorResponse, &buffer);
  auto* params = writer.mutable_payload<att::ErrorResponseParams>();
  params->request_opcode = htole16(opcode);
  params->attribute_handle = htole16(handle);
  params->error_code = ecode;

  Send(conn, buffer);
}

}  // namespace testing
}  // namespace bt
