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

#include <base/logging.h>
#include <hardware/bluetooth.h>
#include <hardware/bt_le_audio.h>

#include <vector>

#include "bta_le_audio_api.h"
#include "btif_common.h"
#include "btif_storage.h"
#include "stack/include/btu.h"

using base::Bind;
using base::Unretained;
using bluetooth::le_audio::ConnectionState;
using bluetooth::le_audio::GroupNodeStatus;
using bluetooth::le_audio::GroupStatus;
using bluetooth::le_audio::LeAudioClientCallbacks;
using bluetooth::le_audio::LeAudioClientInterface;

namespace {
class LeAudioClientInterfaceImpl;
std::unique_ptr<LeAudioClientInterface> leAudioInstance;

class LeAudioClientInterfaceImpl : public LeAudioClientInterface,
                                   public LeAudioClientCallbacks {
  ~LeAudioClientInterfaceImpl() = default;

  void OnConnectionState(ConnectionState state,
                         const RawAddress& address) override {
    do_in_jni_thread(FROM_HERE, Bind(&LeAudioClientCallbacks::OnConnectionState,
                                     Unretained(callbacks), state, address));
  }

  void OnGroupStatus(int group_id, GroupStatus group_status) override {
    do_in_jni_thread(FROM_HERE,
                     Bind(&LeAudioClientCallbacks::OnGroupStatus,
                          Unretained(callbacks), group_id, group_status));
  }

  void OnGroupNodeStatus(const RawAddress& addr, int group_id,
                         GroupNodeStatus node_status) override {
    do_in_jni_thread(FROM_HERE,
                     Bind(&LeAudioClientCallbacks::OnGroupNodeStatus,
                          Unretained(callbacks), addr, group_id, node_status));
  }

  void OnAudioConf(uint8_t direction, int group_id, uint32_t snk_audio_location,
                   uint32_t src_audio_location, uint16_t avail_cont) override {
    do_in_jni_thread(FROM_HERE,
                     Bind(&LeAudioClientCallbacks::OnAudioConf,
                          Unretained(callbacks), direction, group_id,
                          snk_audio_location, src_audio_location, avail_cont));
  }

  void Initialize(LeAudioClientCallbacks* callbacks) override {
    this->callbacks = callbacks;
    do_in_main_thread(
        FROM_HERE, Bind(&LeAudioClient::Initialize, this,
                        jni_thread_wrapper(
                            FROM_HERE, Bind(&btif_storage_load_bonded_leaudio)),
                        base::Bind([]() -> bool {
                          return LeAudioHalVerifier::SupportsLeAudio();
                        })));
  }

  void Cleanup(void) override {
    DVLOG(2) << __func__;
    do_in_main_thread(FROM_HERE, Bind(&LeAudioClient::Cleanup));
  }

  void RemoveDevice(const RawAddress& address) override {
    DVLOG(2) << __func__ << " address: " << address;
    do_in_main_thread(FROM_HERE,
                      Bind(&LeAudioClient::RemoveDevice,
                           Unretained(LeAudioClient::Get()), address));

    do_in_jni_thread(FROM_HERE, Bind(&btif_storage_remove_leaudio, address));
  }

  void Connect(const RawAddress& address) override {
    DVLOG(2) << __func__ << " address: " << address;
    do_in_main_thread(FROM_HERE,
                      Bind(&LeAudioClient::Connect,
                           Unretained(LeAudioClient::Get()), address));
  }

  void Disconnect(const RawAddress& address) override {
    DVLOG(2) << __func__ << " address: " << address;
    do_in_main_thread(FROM_HERE,
                      Bind(&LeAudioClient::Disconnect,
                           Unretained(LeAudioClient::Get()), address));
    do_in_jni_thread(
        FROM_HERE, Bind(&btif_storage_set_leaudio_autoconnect, address, false));
  }

  void GroupAddNode(const int group_id, const RawAddress& address) override {
    DVLOG(2) << __func__ << " group_id: " << group_id
             << " address: " << address;
    do_in_main_thread(
        FROM_HERE, Bind(&LeAudioClient::GroupAddNode,
                        Unretained(LeAudioClient::Get()), group_id, address));
  }

  void GroupRemoveNode(const int group_id, const RawAddress& address) override {
    DVLOG(2) << __func__ << " group_id: " << group_id
             << " address: " << address;
    do_in_main_thread(
        FROM_HERE, Bind(&LeAudioClient::GroupRemoveNode,
                        Unretained(LeAudioClient::Get()), group_id, address));
  }

  void GroupSetActive(const int group_id) override {
    DVLOG(2) << __func__ << " group_id: " << group_id;
    do_in_main_thread(FROM_HERE,
                      Bind(&LeAudioClient::GroupSetActive,
                           Unretained(LeAudioClient::Get()), group_id));
  }

 private:
  LeAudioClientCallbacks* callbacks;
};

} /* namespace */

LeAudioClientInterface* btif_le_audio_get_interface() {
  if (!leAudioInstance) {
    leAudioInstance.reset(new LeAudioClientInterfaceImpl());
  }

  return leAudioInstance.get();
}
