// Copyright 2017 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "midis/device.h"

#include <alsa/asoundlib.h>
#include <fcntl.h>
#include <sys/socket.h>

#include <base/bind.h>
#include <base/callback.h>
#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/stringprintf.h>

#include "midis/constants.h"
#include "midis/subdevice_client_fd_holder.h"

namespace {

const unsigned int kInputPortCaps =
    SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_READ;
const unsigned int kOutputPortCaps =
    SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE;

}  // namespace

namespace midis {

Device::Device(const std::string& name,
               const std::string& manufacturer,
               uint32_t card,
               uint32_t device,
               uint32_t num_subdevices,
               uint32_t flags,
               InPort::SubscribeCallback in_sub_cb,
               OutPort::SubscribeCallback out_sub_cb,
               InPort::DeletionCallback in_del_cb,
               OutPort::DeletionCallback out_del_cb,
               OutPort::SendMidiDataCallback send_data_cb,
               const std::map<uint32_t, unsigned int>& port_caps)
    : name_(name),
      manufacturer_(manufacturer),
      card_(card),
      device_(device),
      num_subdevices_(num_subdevices),
      flags_(flags),
      in_sub_cb_(std::move(in_sub_cb)),
      out_sub_cb_(std::move(out_sub_cb)),
      in_del_cb_(std::move(in_del_cb)),
      out_del_cb_(std::move(out_del_cb)),
      send_data_cb_(send_data_cb),
      port_caps_(port_caps),
      weak_factory_(this) {
  LOG(INFO) << "Device created: " << name_;
}

Device::~Device() {
  StopMonitoring();
}

void Device::StopMonitoring() {
  // Cancel all the clients FDs who were listening / writing to this device.
  client_fds_.clear();
  in_ports_.clear();
  out_ports_.clear();
}

bool Device::StartMonitoring() {
  for (auto& it : port_caps_) {
    if (it.second & kInputPortCaps) {
      auto in_port = InPort::Create(device_, it.first, in_sub_cb_, in_del_cb_);
      if (in_port) {
        in_ports_.emplace(it.first, std::move(in_port));
        LOG(INFO) << "Input Port created for port:" << it.first;
      }
    }
    if (it.second & kOutputPortCaps) {
      auto out_port = OutPort::Create(device_, it.first, out_sub_cb_,
                                      out_del_cb_, send_data_cb_);
      if (out_port) {
        out_ports_.emplace(it.first, std::move(out_port));
        LOG(INFO) << "Outpot Port created for port:" << it.first;
      }
    }
  }
  return true;
}

void Device::HandleReceiveData(const char* buffer,
                               uint32_t subdevice,
                               size_t buf_len) const {
  // NOTE: We don't check whether this subdevice can actually receive data
  // because the data is coming in from the a MIDI H/W port, and so if data is
  // being generated here, it must be from a valid source.
  auto list_it = client_fds_.find(subdevice);
  if (list_it != client_fds_.end()) {
    for (const auto& id_fd_entry : list_it->second) {
      id_fd_entry->WriteDeviceDataToClient(buffer, buf_len);
    }
  }
}

void Device::RemoveClientFromDevice(uint32_t client_id) {
  LOG(INFO) << "Removing the client: " << client_id
            << " from all device watchers for device: " << name_;
  for (auto list_it = client_fds_.begin(); list_it != client_fds_.end();) {
    // First remove all clients in a subdevice.
    for (auto it = list_it->second.begin(); it != list_it->second.end();) {
      if (it->get()->GetClientId() == client_id) {
        LOG(INFO) << "Found client: " << client_id << " in list. deleting";
        it = list_it->second.erase(it);
      } else {
        ++it;
      }
    }
    // If no clients remain, remove the subdevice entry from the map.
    if (list_it->second.empty()) {
      client_fds_.erase(list_it++);
    } else {
      ++list_it;
    }
  }

  if (client_fds_.empty()) {
    StopMonitoring();
  }
}

void Device::WriteClientDataToDevice(uint32_t subdevice_id,
                                     const uint8_t* buffer,
                                     size_t buf_len) {
  // Check whether this port supports output, otherwise just drop the data, and
  // print a warning.
  auto it = out_ports_.find(subdevice_id);
  if (it == out_ports_.end()) {
    LOG(WARNING)
        << "Data received on port: " << subdevice_id
        << " which doesn't support writing to MIDI device; dropping data";
    return;
  }
  it->second->SendData(buffer, buf_len);
}

base::ScopedFD Device::AddClientToReadSubdevice(uint32_t client_id,
                                                uint32_t subdevice_id) {
  if (client_fds_.empty()) {
    if (!StartMonitoring()) {
      LOG(ERROR) << "Couldn't start monitoring device: " << name_;
      StopMonitoring();
      return base::ScopedFD();
    }
  }

  int sock_fd[2];
  int ret = socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sock_fd);
  if (ret < 0) {
    PLOG(ERROR) << "socketpair for client_id: " << client_id
                << " device_id: " << device_ << " subdevice: " << subdevice_id
                << "failed.";
    return base::ScopedFD();
  }

  base::ScopedFD server_fd(sock_fd[0]);
  base::ScopedFD client_fd(sock_fd[1]);

  auto id_fd_list = client_fds_.find(subdevice_id);
  if (id_fd_list == client_fds_.end()) {
    std::vector<std::unique_ptr<SubDeviceClientFdHolder>> list_entries;

    list_entries.emplace_back(SubDeviceClientFdHolder::Create(
        client_id, subdevice_id, std::move(server_fd),
        base::BindRepeating(&Device::WriteClientDataToDevice,
                            weak_factory_.GetWeakPtr())));

    client_fds_.emplace(subdevice_id, std::move(list_entries));
  } else {
    for (auto const& pair : id_fd_list->second) {
      if (pair->GetClientId() == client_id) {
        LOG(INFO) << "Client id: " << client_id
                  << " already registered to"
                     " subdevice: "
                  << subdevice_id << ".";
        return base::ScopedFD();
      }
    }
    id_fd_list->second.emplace_back(SubDeviceClientFdHolder::Create(
        client_id, subdevice_id, std::move(server_fd),
        base::BindRepeating(&Device::WriteClientDataToDevice,
                            weak_factory_.GetWeakPtr())));
  }

  return client_fd;
}

}  // namespace midis
