// Copyright 2020 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 "iioservice/daemon/sensor_device_impl.h"

#include <utility>

#include <base/bind.h>
#include <base/strings/string_util.h>
#include <libmems/common_types.h>
#include <libmems/iio_channel.h>

#include "iioservice/include/common.h"

namespace iioservice {

// static
void SensorDeviceImpl::SensorDeviceImplDeleter(SensorDeviceImpl* device) {
  if (device == nullptr)
    return;

  if (!device->ipc_task_runner_->RunsTasksInCurrentSequence()) {
    device->ipc_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&SensorDeviceImpl::SensorDeviceImplDeleter, device));
    return;
  }

  delete device;
}

// static
SensorDeviceImpl::ScopedSensorDeviceImpl SensorDeviceImpl::Create(
    scoped_refptr<base::SequencedTaskRunner> ipc_task_runner,
    libmems::IioContext* context) {
  DCHECK(ipc_task_runner->RunsTasksInCurrentSequence());

  ScopedSensorDeviceImpl device(nullptr, SensorDeviceImplDeleter);

  std::unique_ptr<base::Thread> thread(new base::Thread("SensorDeviceImpl"));
  if (!thread->StartWithOptions(
          base::Thread::Options(base::MessagePumpType::IO, 0))) {
    LOGF(ERROR) << "Failed to start thread with TYPE_IO";
    device.reset();
    return device;
  }

  device.reset(new SensorDeviceImpl(std::move(ipc_task_runner), context,
                                    std::move(thread)));

  return device;
}

SensorDeviceImpl::~SensorDeviceImpl() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  samples_handlers_.clear();
  sample_thread_->Stop();
  receiver_set_.Clear();
  clients_.clear();
}

void SensorDeviceImpl::AddReceiver(
    int32_t iio_device_id,
    mojo::PendingReceiver<cros::mojom::SensorDevice> request) {
  ipc_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&SensorDeviceImpl::AddReceiverOnThread,
                                weak_factory_.GetWeakPtr(), iio_device_id,
                                std::move(request)));
}

void SensorDeviceImpl::SetTimeout(uint32_t timeout) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  clients_[id].timeout = timeout;
}

void SensorDeviceImpl::GetAttributes(const std::vector<std::string>& attr_names,
                                     GetAttributesCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  std::vector<base::Optional<std::string>> values;
  values.reserve(attr_names.size());
  for (const auto& attr_name : attr_names) {
    auto value_opt = clients_[id].iio_device->ReadStringAttribute(attr_name);
    if (value_opt.has_value()) {
      value_opt =
          base::TrimString(value_opt.value(), base::StringPiece("\0\n", 2),
                           base::TRIM_TRAILING)
              .as_string();
    }

    values.push_back(std::move(value_opt));
  }

  std::move(callback).Run(std::move(values));
}

void SensorDeviceImpl::SetFrequency(double frequency,
                                    SetFrequencyCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  ClientData& client = clients_[id];

  if (AddSamplesHandlerIfNotSet(client.iio_device)) {
    samples_handlers_.at(client.iio_device)
        ->UpdateFrequency(&client, frequency, std::move(callback));
    return;
  }

  // Failed to add the SamplesHandler
  client.frequency = frequency;
  std::move(callback).Run(frequency);
}

void SensorDeviceImpl::StartReadingSamples(
    mojo::PendingRemote<cros::mojom::SensorDeviceSamplesObserver> observer) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  ClientData& client = clients_[id];

  if (client.observer.is_bound()) {
    LOGF(ERROR) << "Reading already started: " << id;
    mojo::Remote<cros::mojom::SensorDeviceSamplesObserver>(std::move(observer))
        ->OnErrorOccurred(cros::mojom::ObserverErrorType::ALREADY_STARTED);
    return;
  }

  if (!AddSamplesHandlerIfNotSet(client.iio_device)) {
    observer.reset();
    return;
  }
  client.observer.Bind(std::move(observer));
  client.observer.set_disconnect_handler(
      base::BindOnce(&SensorDeviceImpl::OnSamplesObserverDisconnect,
                     weak_factory_.GetWeakPtr(), id));

  samples_handlers_.at(client.iio_device)->AddClient(&client);
}

void SensorDeviceImpl::StopReadingSamples() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  StopReadingSamplesOnClient(id);
}

void SensorDeviceImpl::GetAllChannelIds(GetAllChannelIdsCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  auto iio_device = clients_[id].iio_device;
  std::vector<std::string> chn_ids;
  for (auto iio_channel : iio_device->GetAllChannels())
    chn_ids.push_back(iio_channel->GetId());

  std::move(callback).Run(std::move(chn_ids));
}

void SensorDeviceImpl::SetChannelsEnabled(
    const std::vector<int32_t>& iio_chn_indices,
    bool en,
    SetChannelsEnabledCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  ClientData& client = clients_[id];

  if (AddSamplesHandlerIfNotSet(client.iio_device)) {
    samples_handlers_.at(client.iio_device)
        ->UpdateChannelsEnabled(&client, std::move(iio_chn_indices), en,
                                std::move(callback));
    return;
  }

  // List of channels failed to enabled.
  std::vector<int32_t> failed_indices;

  if (en) {
    for (int32_t chn_index : iio_chn_indices) {
      auto chn = client.iio_device->GetChannel(chn_index);
      if (!chn || !chn->IsEnabled()) {
        LOG(ERROR) << "Failed to enable chn with index: " << chn_index;
        failed_indices.push_back(chn_index);
        continue;
      }

      client.enabled_chn_indices.emplace(chn_index);
    }
  } else {
    for (int32_t chn_index : iio_chn_indices)
      client.enabled_chn_indices.erase(chn_index);
  }

  std::move(callback).Run(std::move(failed_indices));
}

void SensorDeviceImpl::GetChannelsEnabled(
    const std::vector<int32_t>& iio_chn_indices,
    GetChannelsEnabledCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  ClientData& client = clients_[id];

  if (AddSamplesHandlerIfNotSet(client.iio_device)) {
    samples_handlers_.at(client.iio_device)
        ->GetChannelsEnabled(&client, std::move(iio_chn_indices),
                             std::move(callback));
    return;
  }

  // List of channels failed to enabled.
  std::vector<bool> enabled;

  for (int32_t chn_index : iio_chn_indices) {
    enabled.push_back(client.enabled_chn_indices.find(chn_index) !=
                      client.enabled_chn_indices.end());
  }

  std::move(callback).Run(std::move(enabled));
}

void SensorDeviceImpl::GetChannelsAttributes(
    const std::vector<int32_t>& iio_chn_indices,
    const std::string& attr_name,
    GetChannelsAttributesCallback callback) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();
  ClientData& client = clients_[id];
  auto iio_device = client.iio_device;

  std::vector<base::Optional<std::string>> values;

  for (int32_t chn_index : iio_chn_indices) {
    auto chn = iio_device->GetChannel(chn_index);

    if (!chn) {
      LOG(ERROR) << "Cannot find chn with index: " << chn_index;
      values.push_back(base::nullopt);
      continue;
    }

    base::Optional<std::string> value_opt = chn->ReadStringAttribute(attr_name);
    if (value_opt.has_value()) {
      value_opt =
          base::TrimString(value_opt.value(), base::StringPiece("\0\n", 2),
                           base::TRIM_TRAILING)
              .as_string();
    }

    values.push_back(value_opt);
  }

  std::move(callback).Run(std::move(values));
}

SensorDeviceImpl::SensorDeviceImpl(
    scoped_refptr<base::SequencedTaskRunner> ipc_task_runner,
    libmems::IioContext* context,
    std::unique_ptr<base::Thread> thread)
    : ipc_task_runner_(std::move(ipc_task_runner)),
      context_(std::move(context)),
      sample_thread_(std::move(thread)) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  receiver_set_.set_disconnect_handler(base::BindRepeating(
      &SensorDeviceImpl::OnSensorDeviceDisconnect, weak_factory_.GetWeakPtr()));
}

void SensorDeviceImpl::AddReceiverOnThread(
    int32_t iio_device_id,
    mojo::PendingReceiver<cros::mojom::SensorDevice> request) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  auto iio_device = context_->GetDeviceById(iio_device_id);
  if (!iio_device) {
    LOGF(ERROR) << "Invalid iio_device_id: " << iio_device_id;
    return;
  }

  mojo::ReceiverId id =
      receiver_set_.Add(this, std::move(request), ipc_task_runner_);
  clients_[id].id = id;
  clients_[id].iio_device = iio_device;
}

void SensorDeviceImpl::OnSensorDeviceDisconnect() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  mojo::ReceiverId id = receiver_set_.current_receiver();

  LOGF(INFO) << "SensorDevice disconnected. ReceiverId: " << id;
  StopReadingSamplesOnClient(id);

  // Run RemoveClient(id) on |sample_thread_| so that tasks to remove the client
  // in SamplesHandler have been done.
  sample_thread_->task_runner()->PostTask(
      FROM_HERE, base::BindOnce(&SensorDeviceImpl::RemoveClient,
                                base::Unretained(this), id));
}

void SensorDeviceImpl::RemoveClient(mojo::ReceiverId id) {
  DCHECK(sample_thread_->task_runner()->RunsTasksInCurrentSequence());

  clients_.erase(id);
}

void SensorDeviceImpl::OnSamplesObserverDisconnect(mojo::ReceiverId id) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  LOGF(ERROR) << "SamplesObserver disconnected. ReceiverId: " << id;
  StopReadingSamplesOnClient(id);
}

void SensorDeviceImpl::StopReadingSamplesOnClient(mojo::ReceiverId id) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  ClientData& client = clients_[id];

  if (!client.observer.is_bound()) {
    // The client is not reading samples.
    return;
  }

  if (samples_handlers_.find(client.iio_device) != samples_handlers_.end())
    samples_handlers_.at(client.iio_device)->RemoveClient(&client);

  client.observer.reset();
}

bool SensorDeviceImpl::AddSamplesHandlerIfNotSet(
    libmems::IioDevice* iio_device) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  if (samples_handlers_.find(iio_device) != samples_handlers_.end())
    return true;

  SamplesHandler::ScopedSamplesHandler handler = {
      nullptr, SamplesHandler::SamplesHandlerDeleter};

  auto sample_cb = base::BindRepeating(
      &SensorDeviceImpl::OnSampleUpdatedCallback, weak_factory_.GetWeakPtr());
  auto error_cb = base::BindRepeating(
      &SensorDeviceImpl::OnErrorOccurredCallback, weak_factory_.GetWeakPtr());

  handler = SamplesHandler::Create(ipc_task_runner_,
                                   sample_thread_->task_runner(), iio_device,
                                   std::move(sample_cb), std::move(error_cb));

  if (!handler) {
    LOGF(ERROR) << "Failed to create the samples handler for device: "
                << iio_device->GetId();
    return false;
  }

  samples_handlers_.emplace(iio_device, std::move(handler));
  return true;
}

void SensorDeviceImpl::OnSampleUpdatedCallback(
    mojo::ReceiverId id, libmems::IioDevice::IioSample sample) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  auto it = clients_.find(id);
  if (it == clients_.end()) {
    LOGF(WARNING) << "Sample not sent, as the client doesn't exist: " << id;
    return;
  }

  if (!it->second.observer.is_bound()) {
    LOGF(WARNING) << "Sample not sent, as the client has stopped reading: "
                  << id;
    return;
  }

  it->second.observer->OnSampleUpdated(std::move(sample));
}

void SensorDeviceImpl::OnErrorOccurredCallback(
    mojo::ReceiverId id, cros::mojom::ObserverErrorType type) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  auto it = clients_.find(id);
  if (it == clients_.end()) {
    LOGF(WARNING) << "Error not sent, as the client doesn't exist: " << id;
    return;
  }

  if (!it->second.observer.is_bound()) {
    LOGF(WARNING) << "Sample not sent, as the client has stopped reading: "
                  << id;
    return;
  }

  it->second.observer->OnErrorOccurred(type);
}

}  // namespace iioservice
