// Copyright 2017 The Chromium OS 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 "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/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_(in_sub_cb),
      out_sub_cb_(out_sub_cb),
      in_del_cb_(in_del_cb),
      out_del_cb_(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::Bind(&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::Bind(&Device::WriteClientDataToDevice,
                   weak_factory_.GetWeakPtr())));
  }

  return client_fd;
}

}  // namespace midis
