/*
 * Copyright 2020 HIMSA II K/S - www.himsa.com. Represented by EHIMA -
 * www.ehima.com
 *
 * 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.
 */

#pragma once

#include <algorithm>
#include <deque>

#include "os/logging/log_adapter.h"
#include "stack/gatt/gatt_int.h"
#include "types/raw_address.h"

#define EATT_MIN_MTU_MPS (64)
#define EATT_DEFAULT_MTU (256)
#define EATT_MAX_TX_MTU  (1024)
#define EATT_ALL_CIDS (0xFFFF)

namespace bluetooth {
namespace eatt {

/* Enums */
enum class EattChannelState : uint8_t {
  EATT_CHANNEL_PENDING = 0x00,
  EATT_CHANNEL_OPENED,
  EATT_CHANNEL_RECONFIGURING,
};

class EattChannel {
 public:
  /* Pointer to EattDevice */
  RawAddress bda_;
  uint16_t cid_;
  uint16_t tx_mtu_;
  uint16_t rx_mtu_;
  EattChannelState state_;

  /* Used to keep server commands */
  tGATT_SR_CMD server_outstanding_cmd_;
  /* Used to veryfy indication confirmation*/
  uint16_t indicate_handle_;
  /* local app confirm to indication timer */
  alarm_t* ind_ack_timer_;
  /* indication confirmation timer */
  alarm_t* ind_confirmation_timer_;
  /* GATT client command queue */
  std::deque<tGATT_CMD_Q> cl_cmd_q_;

  EattChannel(RawAddress& bda, uint16_t cid, uint16_t tx_mtu, uint16_t rx_mtu)
      : bda_(bda),
        cid_(cid),
        rx_mtu_(rx_mtu),
        state_(EattChannelState::EATT_CHANNEL_PENDING),
        indicate_handle_(0),
        ind_ack_timer_(NULL),
        ind_confirmation_timer_(NULL) {
    cl_cmd_q_ = std::deque<tGATT_CMD_Q>();
    EattChannelSetTxMTU(tx_mtu);
  }

  ~EattChannel() {
    if (ind_ack_timer_ != NULL) {
      alarm_free(ind_ack_timer_);
    }

    if (ind_confirmation_timer_ != NULL) {
      alarm_free(ind_confirmation_timer_);
    }
  }

  void EattChannelSetState(EattChannelState state) {
    if (state_ == EattChannelState::EATT_CHANNEL_PENDING) {
      if (state == EattChannelState::EATT_CHANNEL_OPENED) {
        memset(&server_outstanding_cmd_, 0, sizeof(tGATT_SR_CMD));
        char name[64];
        sprintf(name, "eatt_ind_ack_timer_%s_cid_0x%04x",
                ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_);
        ind_ack_timer_ = alarm_new(name);

        sprintf(name, "eatt_ind_conf_timer_%s_cid_0x%04x",
                ADDRESS_TO_LOGGABLE_CSTR(bda_), cid_);
        ind_confirmation_timer_ = alarm_new(name);
      }
    }
    state_ = state;
  }

  void EattChannelSetTxMTU(uint16_t tx_mtu) {
    this->tx_mtu_ = std::min<uint16_t>(tx_mtu, EATT_MAX_TX_MTU);
  }
};

/* Interface class */
class EattExtension {
 public:
  EattExtension();
  EattExtension(const EattExtension&) = delete;
  EattExtension& operator=(const EattExtension&) = delete;

  virtual ~EattExtension();

  static EattExtension* GetInstance() {
    static EattExtension* instance = new EattExtension();
    return instance;
  }

  static void AddFromStorage(const RawAddress& bd_addr);

  /**
   * Checks if EATT is supported on peer device.
   *
   * @param bd_addr peer device address
   */
  virtual bool IsEattSupportedByPeer(const RawAddress& bd_addr);

  /**
   * Connect at maximum 5 EATT channels to peer device.
   *
   * @param bd_addr peer device address
   */
  virtual void Connect(const RawAddress& bd_addr);

  /**
   * Disconnect all EATT channels to peer device.
   *
   * @param bd_addr peer device address
   * @param cid remote channel id (EATT_ALL_CIDS for all)
   */
  virtual void Disconnect(const RawAddress& bd_addr,
                          uint16_t cid = EATT_ALL_CIDS);

  /**
   * Reconfigure EATT channel for give CID
   *
   * @param bd_addr peer device address
   * @param cid channel id
   * @param mtu new maximum transmit unit available of local device
   */
  virtual void Reconfigure(const RawAddress& bd_addr, uint16_t cid,
                           uint16_t mtu);

  /**
   * Reconfigure all EATT channels to peer device.
   *
   * @param bd_addr peer device address
   * @param mtu new maximum transmit unit available of local device
   */
  virtual void ReconfigureAll(const RawAddress& bd_addr, uint16_t mtu);

  /* Below methods required by GATT implementation */

  /**
   * Find EATT channel by cid.
   *
   * @param bd_addr peer device address
   * @param cid channel id
   *
   * @return Eatt Channel instance.
   */
  virtual EattChannel* FindEattChannelByCid(const RawAddress& bd_addr,
                                            uint16_t cid);

  /**
   * Find EATT channel by transaction id.
   *
   * @param bd_addr peer device address
   * @param trans_id transaction id
   *
   * @return pointer to EATT channel.
   */
  virtual EattChannel* FindEattChannelByTransId(const RawAddress& bd_addr,
                                                uint32_t trans_id);

  /**
   * Check if EATT channel on given handle is waiting for a indication
   * confirmation
   *
   * @param bd_addr peer device address
   * @param indication_handle handle of the pending indication
   *
   * @return true if confirmation is pending false otherwise
   */
  virtual bool IsIndicationPending(const RawAddress& bd_addr,
                                   uint16_t indication_handle);

  /**
   * Get EATT channel available for indication.
   *
   * @param bd_addr peer device address
   *
   * @return pointer to EATT channel.
   */
  virtual EattChannel* GetChannelAvailableForIndication(
      const RawAddress& bd_addr);

  /**
   * Free Resources.
   *
   * (Maybe not needed)
   * @param bd_addr peer device address
   *
   */
  virtual void FreeGattResources(const RawAddress& bd_addr);

  /**
   * Check if there is any EATT channels having some msg in its send queue
   *
   * @param bd_addr peer device address
   *
   * @return true when there is at least one EATT channel ready to send
   */
  virtual bool IsOutstandingMsgInSendQueue(const RawAddress& bd_addr);

  /**
   * Get EATT channel ready to send.
   *
   * @param bd_addr peer device address
   *
   * @return pointer to EATT channel.
   */
  virtual EattChannel* GetChannelWithQueuedDataToSend(
      const RawAddress& bd_addr);

  /**
   * Get EATT channel available to send GATT request.
   *
   * @param bd_addr peer device address
   *
   * @return pointer to EATT channel.
   */
  virtual EattChannel* GetChannelAvailableForClientRequest(
      const RawAddress& bd_addr);

  /**
   * Start GATT indication timer per CID.
   *
   * @param bd_addr peer device address
   * @param cid channel id
   */
  virtual void StartIndicationConfirmationTimer(const RawAddress& bd_addr,
                                                uint16_t cid);

  /**
   * Stop GATT indication timer per CID.
   *
   * @param bd_addr peer device address
   * @param cid channel id
   */
  virtual void StopIndicationConfirmationTimer(const RawAddress& bd_addr,
                                               uint16_t cid);

  /**
   *  Start application time for incoming indication on given CID
   *
   * @param bd_addr peer device address
   * @param cid channel id
   */
  virtual void StartAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid);

  /**
   *  Stop application time for incoming indication on given CID
   *
   * @param bd_addr peer device address
   * @param cid channel id
   */
  virtual void StopAppIndicationTimer(const RawAddress& bd_addr, uint16_t cid);

  /**
   * Starts the EattExtension module
   */
  void Start();

  /**
   * Stops the EattExtension module
   */
  void Stop();

 private:
  struct impl;
  std::unique_ptr<impl> pimpl_;
};

}  // namespace eatt
}  // namespace bluetooth
