/*
 * Copyright 2018 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.
 */

#pragma once

#include <base/bind.h>
#include <base/memory/weak_ptr.h>
#include <map>
#include <memory>

#include "avrcp_internal.h"
#include "packet/avrcp/avrcp_packet.h"
#include "packet/base/packet.h"
#include "profile/avrcp/device.h"
#include "raw_address.h"

namespace bluetooth {
namespace avrcp {

// TODO: Remove the singleton design structure for this class.
// AvrcpTargetService is already a singleton and can manage the lifetime of this
// object. multiple singleton objects can lead to code that is hard to test and
// have hard to debug lifetimes.

// TODO (apanicke): Use a device factory instead of just the constructor in
// order to create device objects. This will allow us to create specific device
// classes that can provide interop fixes for certain badly behaving devices.

/**
 * ConnectionHandler handles SDP, connecting to remote AVRCP devices
 * and multiplexing/delivering messages to devices.
 */
class ConnectionHandler {
 public:
  /**
   * This callback is used to return a new device after a connection attempt.
   * A reference to the new Avrcp device is located in the shared_ptr.
   * If there was an issue during connection the pointer value will be null.
   */
  using ConnectionCallback = base::Callback<void(std::shared_ptr<Device>)>;

  /**
   * Initializes the singleton instance and sets up SDP. Also Opens the
   * AVRCP Acceptor to receive connection requests from a remote device.
   *
   * Params:
   * callback - A callback that gets called any time a new AVRCP Device
   *            is connected. Will return nullpointer if a device fails
   *            to connect via ConnectDevice();
   *
   * TODO: Add message loop to determine which thread events are posted to
   */
  static bool Initialize(const ConnectionCallback& callback,
                         AvrcpInterface* avrcp, SdpInterface* sdp,
                         VolumeInterface* vol);

  /**
   * Clears the singleton and tears down SDP
   */
  static bool CleanUp();

  /**
   * Get the singleton instance of Connection Handler
   */
  static ConnectionHandler* Get();

  /**
   * Attempt to connect AVRCP on a device. The callback will be called with
   * either a smart pointer pointing to the connected AVRCP device or null
   * if the connection failed.
   *
   * The order of operations for this function is as follows.
   *   1. Perform SDP on remote device
   *   2. Connect the AVCTP Channel
   *   2. (Optional) If supported connect the AVCTP Browse channel
   *   4. Call the provided callback with the new
   *
   * Params:
   * bdaddr - Bluetooth address of device to connect to
   * callback - The function that gets called when a connection succeeds or
   *            fails. The pointer being cleared implies that the connection
   *            failed.
   *
   * Returns:
   * true if the connection attempt starts, false if there are no resources to
   * connect AVRCP
   */
  virtual bool ConnectDevice(const RawAddress& bdaddr);

  /**
   * Disconnects AVRCP from a device that was successfully connected too using
   * ConnectionHandler::ConnectDevice
   *
   * Returns:
   * true if the AVRCP was successfully disconnected for the device or false
   * if the device was already disconnected or in an invalid state
   */
  virtual bool DisconnectDevice(const RawAddress& bdaddr);

  /**
   * Indicates the connection status of a device on the BIP OBEX server.
   *
   * This status is used to determine whether we should include image handles
   * when building responses for media item metadata queries.
   */
  virtual void SetBipClientStatus(const RawAddress& bdaddr, bool connected);

  virtual std::vector<std::shared_ptr<Device>> GetListOfDevices() const;

  /**
   * Provide a custom ConnectionHandler that will be returned by Get().
   * Initialize and CleanUp should not be called as the owner of the handler
   * determines its lifetime.
   */
  static void InitForTesting(ConnectionHandler* handler);

 private:
  AvrcpInterface* avrc_;
  SdpInterface* sdp_;
  VolumeInterface* vol_;

  ConnectionCallback connection_cb_;

  std::map<uint8_t, std::shared_ptr<Device>> device_map_;
  // TODO (apanicke): Replace the features with a class that has individual
  // fields.
  std::map<RawAddress, uint16_t> feature_map_;

  static ConnectionHandler* instance_;

  using SdpCallback = base::Callback<void(uint16_t status, uint16_t version,
                                          uint16_t features)>;
  virtual bool SdpLookup(const RawAddress& bdaddr, SdpCallback cb, bool retry);
  void SdpCb(RawAddress bdaddr, SdpCallback cb,
             tSDP_DISCOVERY_DB* disc_db, bool retry, uint16_t status);

  virtual bool AvrcpConnect(bool initiator, const RawAddress& bdaddr);

  // Callbacks when connecting to a device
  void InitiatorControlCb(uint8_t handle, uint8_t event, uint16_t result,
                          const RawAddress* peer_addr);
  void AcceptorControlCb(uint8_t handle, uint8_t event, uint16_t result,
                         const RawAddress* peer_addr);
  void MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
                 tAVRC_MSG* p_msg);

  ConnectionHandler() : weak_ptr_factory_(this){};
  virtual ~ConnectionHandler() = default;

  // Callback for when sending a response to a device
  void SendMessage(uint8_t handle, uint8_t label, bool browse,
                   std::unique_ptr<::bluetooth::PacketBuilder> message);

  base::WeakPtrFactory<ConnectionHandler> weak_ptr_factory_;
  DISALLOW_COPY_AND_ASSIGN(ConnectionHandler);
};

}  // namespace avrcp
}  // namespace bluetooth
