// 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/iioservice_simpleclient/observer_impl.h"

#include <algorithm>
#include <utility>

#include <base/bind.h>

#include "base/time/time.h"
#include "iioservice/include/common.h"
#include "libmems/common_types.h"

namespace iioservice {

namespace {

constexpr int kSetUpChannelTimeoutInMilliseconds = 3000;

// Set the base latency tolerance to half of 100 ms, according to
// https://source.android.com/compatibility/android-cdd#7_3_sensors, as the
// samples may go through a VM and Android sensormanager.
constexpr base::TimeDelta kMaximumBaseLatencyTolerance =
    base::TimeDelta::FromMilliseconds(50);

}  // namespace

// static
void ObserverImpl::ObserverImplDeleter(ObserverImpl* observer) {
  if (observer == nullptr)
    return;

  if (!observer->ipc_task_runner_->RunsTasksInCurrentSequence()) {
    observer->ipc_task_runner_->PostTask(
        FROM_HERE,
        base::BindOnce(&ObserverImpl::ObserverImplDeleter, observer));
    return;
  }

  delete observer;
}

// static
ObserverImpl::ScopedObserverImpl ObserverImpl::Create(
    scoped_refptr<base::SequencedTaskRunner> ipc_task_runner,
    int device_id,
    cros::mojom::DeviceType device_type,
    std::vector<std::string> channel_ids,
    double frequency,
    int timeout,
    QuitCallback quit_callback) {
  ScopedObserverImpl observer(
      new ObserverImpl(ipc_task_runner, device_id, device_type,
                       std::move(channel_ids), frequency, timeout,
                       std::move(quit_callback)),
      ObserverImplDeleter);

  return observer;
}

void ObserverImpl::BindClient(
    mojo::PendingReceiver<cros::mojom::SensorHalClient> client) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!client_.is_bound());

  client_.Bind(std::move(client));
  client_.set_disconnect_handler(base::BindOnce(
      &ObserverImpl::OnClientDisconnect, weak_factory_.GetWeakPtr()));
}

void ObserverImpl::SetUpChannel(
    mojo::PendingRemote<cros::mojom::SensorService> pending_remote) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  DCHECK(!sensor_service_remote_.is_bound());

  sensor_service_remote_.Bind(std::move(pending_remote));
  sensor_service_remote_.set_disconnect_handler(base::BindOnce(
      &ObserverImpl::OnServiceDisconnect, weak_factory_.GetWeakPtr()));

  if (device_id_ < 0)
    GetDeviceIdsByType();
  else
    GetSensorDevice();
}

void ObserverImpl::OnSampleUpdated(
    const base::flat_map<int32_t, int64_t>& sample) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  DCHECK_GT(result_freq_, 0.0);

  if (sample.size() != channel_indices_.size()) {
    LOGF(ERROR) << "Invalid sample size: " << sample.size()
                << ", expected size: " << channel_indices_.size();
  }

  for (auto chn : sample)
    LOGF(INFO) << iio_chn_ids_[chn.first] << ": " << chn.second;

  if (!timestamp_index_.has_value())
    return;

  auto it = sample.find(timestamp_index_.value());
  if (it != sample.end()) {
    base::TimeDelta latency =
        base::TimeTicks::Now() -
        (base::TimeTicks() + base::TimeDelta::FromNanoseconds(it->second));
    LOGF(INFO) << "Latency: " << latency;

    total_latency_ += latency;
    latencies_.push_back(latency);
  }

  if (++num_success_reads_ < kNumSuccessReads)
    return;

  // Don't Change: Used as a check sentence in the tast test.
  LOGF(INFO) << "Number of success reads " << kNumSuccessReads << " achieved";

  // Calculate the latencies only when timestamp channel is enabled.
  if (!latencies_.empty()) {
    base::TimeDelta latency_tolerance =
        kMaximumBaseLatencyTolerance +
        base::TimeDelta::FromSecondsD(1.0 / result_freq_);

    size_t n = latencies_.size();
    std::nth_element(latencies_.begin(), latencies_.begin(), latencies_.end());
    base::TimeDelta min_latency = latencies_[0];

    std::nth_element(latencies_.begin(), latencies_.begin() + n / 2,
                     latencies_.end());
    base::TimeDelta median_latency = latencies_[n / 2];

    std::nth_element(latencies_.begin(), --latencies_.end(), latencies_.end());
    base::TimeDelta max_latency = *(--latencies_.end());

    LOGF(INFO) << "Latency tolerance: " << latency_tolerance;
    LOGF(INFO) << "Max latency      : " << max_latency;
    LOGF(INFO) << "Median latency   : " << median_latency;
    LOGF(INFO) << "Min latency      : " << min_latency;
    LOGF(INFO) << "Mean latency     : " << total_latency_ / n;

    if (max_latency > latency_tolerance) {
      // Don't Change: Used as a check sentence in the tast test.
      LOGF(ERROR) << "Max latency exceeds latency tolerance.";
    }

    if (min_latency < base::TimeDelta::FromSecondsD(0.0)) {
      // Don't Change: Used as a check sentence in the tast test.
      LOGF(ERROR)
          << "Min latency less than zero: a timestamp was set in the past.";
    }
  }

  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::OnErrorOccurred(cros::mojom::ObserverErrorType type) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  // Don't Change: Used as a check sentence in the tast test.
  LOGF(ERROR) << "OnErrorOccurred: " << type;
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

ObserverImpl::ObserverImpl(
    scoped_refptr<base::SequencedTaskRunner> ipc_task_runner,
    int device_id,
    cros::mojom::DeviceType device_type,
    std::vector<std::string> channel_ids,
    double frequency,
    int timeout,
    QuitCallback quit_callback)
    : ipc_task_runner_(ipc_task_runner),
      device_id_(device_id),
      device_type_(device_type),
      channel_ids_(std::move(channel_ids)),
      frequency_(frequency),
      timeout_(timeout),
      quit_callback_(std::move(quit_callback)),
      receiver_(this) {
  ipc_task_runner_->PostDelayedTask(
      FROM_HERE,
      base::BindOnce(&ObserverImpl::SetUpChannelTimeout,
                     weak_factory_.GetWeakPtr()),
      base::TimeDelta::FromMilliseconds(kSetUpChannelTimeoutInMilliseconds));
}

mojo::PendingRemote<cros::mojom::SensorDeviceSamplesObserver>
ObserverImpl::GetRemote() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  auto remote = receiver_.BindNewPipeAndPassRemote();
  receiver_.set_disconnect_handler(base::BindOnce(
      &ObserverImpl::OnObserverDisconnect, weak_factory_.GetWeakPtr()));

  return remote;
}

void ObserverImpl::SetUpChannelTimeout() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  if (sensor_service_remote_.is_bound())
    return;

  // Don't Change: Used as a check sentence in the tast test.
  LOGF(ERROR) << "SetUpChannelTimeout";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::OnClientDisconnect() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  LOGF(ERROR) << "SensorHalClient disconnected";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::OnServiceDisconnect() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  LOGF(ERROR) << "SensorService disconnected";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::OnDeviceDisconnect() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  LOGF(ERROR) << "SensorDevice disconnected";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::OnObserverDisconnect() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  LOGF(ERROR) << "Observer diconnected";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::GetDeviceIdsByType() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());
  DCHECK_NE(device_type_, cros::mojom::DeviceType::NONE);

  sensor_service_remote_->GetDeviceIds(
      device_type_, base::BindOnce(&ObserverImpl::GetDeviceIdsCallback,
                                   weak_factory_.GetWeakPtr()));
}

void ObserverImpl::GetDeviceIdsCallback(
    const std::vector<int32_t>& iio_device_ids) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  if (iio_device_ids.empty()) {
    LOGF(ERROR) << "No device found give device type: " << device_type_;
    std::move(quit_callback_).Run();
  }

  // Take the first id.
  device_id_ = iio_device_ids.front();
  GetSensorDevice();
}

void ObserverImpl::GetSensorDevice() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  if (sensor_device_remote_.is_bound())
    sensor_device_remote_.reset();

  sensor_service_remote_->GetDevice(
      device_id_, sensor_device_remote_.BindNewPipeAndPassReceiver());

  sensor_device_remote_.set_disconnect_handler(base::BindOnce(
      &ObserverImpl::OnDeviceDisconnect, weak_factory_.GetWeakPtr()));
  GetAllChannelIds();
}

void ObserverImpl::GetAllChannelIds() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  sensor_device_remote_->GetAllChannelIds(base::BindOnce(
      &ObserverImpl::GetAllChannelIdsCallback, weak_factory_.GetWeakPtr()));
}

void ObserverImpl::GetAllChannelIdsCallback(
    const std::vector<std::string>& iio_chn_ids) {
  iio_chn_ids_ = std::move(iio_chn_ids);
  channel_indices_.clear();

  for (int32_t i = 0; i < channel_ids_.size(); ++i) {
    for (int32_t j = 0; j < iio_chn_ids_.size(); ++j) {
      if (channel_ids_[i] == iio_chn_ids_[j]) {
        channel_indices_.push_back(j);
        break;
      }
    }
  }

  for (int32_t j = 0; j < iio_chn_ids_.size(); ++j) {
    if (iio_chn_ids_[j].compare(libmems::kTimestampAttr) == 0) {
      timestamp_index_ = j;
      break;
    }
  }

  if (channel_indices_.empty()) {
    LOGF(ERROR) << "No available channels";
    if (quit_callback_)
      std::move(quit_callback_).Run();

    return;
  }

  StartReading();
}

void ObserverImpl::StartReading() {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  sensor_device_remote_->SetTimeout(timeout_);
  sensor_device_remote_->SetFrequency(
      frequency_, base::BindOnce(&ObserverImpl::SetFrequencyCallback,
                                 weak_factory_.GetWeakPtr()));
  sensor_device_remote_->SetChannelsEnabled(
      channel_indices_, true,
      base::BindOnce(&ObserverImpl::SetChannelsEnabledCallback,
                     weak_factory_.GetWeakPtr()));

  sensor_device_remote_->StartReadingSamples(GetRemote());
}

void ObserverImpl::SetFrequencyCallback(double result_freq) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  result_freq_ = result_freq;
  if (result_freq_ > 0.0)
    return;

  LOGF(ERROR) << "Failed to set frequency";
  if (quit_callback_)
    std::move(quit_callback_).Run();
}

void ObserverImpl::SetChannelsEnabledCallback(
    const std::vector<int32_t>& failed_indices) {
  DCHECK(ipc_task_runner_->RunsTasksInCurrentSequence());

  for (int32_t index : failed_indices) {
    LOGF(ERROR) << "Failed channel index: " << index;
    bool found = false;
    for (auto it = channel_indices_.begin(); it != channel_indices_.end();
         ++it) {
      if (index == *it) {
        found = true;
        channel_indices_.erase(it);
        break;
      }
    }

    if (!found)
      LOGF(ERROR) << index << " not in requested indices";
  }

  if (channel_indices_.empty()) {
    LOGF(ERROR) << "No channel enabled";
    if (quit_callback_)
      std::move(quit_callback_).Run();
  }
}

}  // namespace iioservice
