// Copyright 2019 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 <memory>
#include <string>

#include <base/check.h>
#include <base/strings/stringprintf.h>
#include <base/logging.h>

#include "libmems/common_types.h"
#include "libmems/iio_channel_impl.h"
#include "libmems/iio_context_impl.h"
#include "libmems/iio_device_impl.h"
#include "libmems/iio_device_trigger_impl.h"

namespace libmems {

IioContextImpl::IioContextImpl() {
  Reload();
}

void IioContextImpl::Reload() {
  // This context will only be destroyed when the entire IioContextImpl goes
  // out of scope. This is done in the interest of not having to invalidate
  // existing iio_device pointers, as their lifetime is statically bound to the
  // context that created them (and contexts are themselves static objects that
  // do not update as devices are added and/or removed at runtime).
  context_.push_back({iio_create_local_context(), iio_context_destroy});
}

bool IioContextImpl::IsValid() const {
  return GetCurrentContext() != nullptr;
}

iio_context* IioContextImpl::GetCurrentContext() const {
  if (context_.empty())
    return nullptr;
  return context_.back().get();
}

bool IioContextImpl::SetTimeout(uint32_t timeout) {
  if (!IsValid())
    return false;

  int error = iio_context_set_timeout(GetCurrentContext(), timeout);
  if (error) {
    char errMsg[kErrorBufferSize];
    iio_strerror(-error, errMsg, sizeof(errMsg));
    LOG(ERROR) << "Unable to set timeout " << timeout << ": " << errMsg;

    return false;
  }

  return true;
}

std::vector<IioDevice*> IioContextImpl::GetDevicesByName(
    const std::string& name) {
  return GetByName(name, &devices_);
}

IioDevice* IioContextImpl::GetDeviceById(int id) {
  return GetById(id, &devices_);
}

std::vector<IioDevice*> IioContextImpl::GetAllDevices() {
  return GetAll(&devices_);
}

std::vector<IioDevice*> IioContextImpl::GetTriggersByName(
    const std::string& name) {
  return GetByName(name, &triggers_);
}

IioDevice* IioContextImpl::GetTriggerById(int id) {
  return GetById(id, &triggers_);
}

std::vector<IioDevice*> IioContextImpl::GetAllTriggers() {
  return GetAll(&triggers_);
}

template <typename T>
IioDevice* IioContextImpl::GetById(
    int id, std::map<int, std::unique_ptr<T>>* devices_map) {
  if (!IsValid())
    return nullptr;

  auto it_dev = devices_map->find(id);
  if (it_dev != devices_map->end())
    return it_dev->second.get();

  std::string id_str = T::GetStringFromId(id);

  iio_device* device =
      iio_context_find_device(GetCurrentContext(), id_str.c_str());
  if (!device)
    return nullptr;

  devices_map->emplace(id, std::make_unique<T>(this, device));

  return devices_map->at(id).get();
}

template <typename T>
std::vector<IioDevice*> IioContextImpl::GetByName(
    const std::string& name, std::map<int, std::unique_ptr<T>>* devices_map) {
  std::vector<IioDevice*> devices;
  if (!IsValid())
    return devices;

  iio_context* ctx = GetCurrentContext();
  uint32_t dev_count = iio_context_get_devices_count(ctx);

  for (uint32_t i = 0; i < dev_count; ++i) {
    iio_device* dev = iio_context_get_device(ctx, i);
    if (!dev) {
      LOG(WARNING) << "Unable to get " << i << "th device";
      continue;
    }

    const char* id_str = iio_device_get_id(dev);
    if (!id_str)
      continue;

    auto id = T::GetIdFromString(id_str);
    if (!id.has_value())
      continue;

    const char* dev_name = iio_device_get_name(dev);
    if (dev_name && name.compare(dev_name) == 0)
      devices.push_back(GetById(id.value(), devices_map));
  }

  return devices;
}

template <typename T>
std::vector<IioDevice*> IioContextImpl::GetAll(
    std::map<int, std::unique_ptr<T>>* devices_map) {
  std::vector<IioDevice*> devices;
  if (!IsValid())
    return devices;

  iio_context* ctx = GetCurrentContext();
  uint32_t dev_count = iio_context_get_devices_count(ctx);

  for (uint32_t i = 0; i < dev_count; ++i) {
    iio_device* dev = iio_context_get_device(ctx, i);
    if (!dev) {
      LOG(WARNING) << "Unable to get " << i << "th device";
      continue;
    }

    const char* id_str = iio_device_get_id(dev);
    if (!id_str)
      continue;

    auto id = T::GetIdFromString(id_str);
    if (!id.has_value())
      continue;

    devices.push_back(GetById(id.value(), devices_map));
  }

  return devices;
}

}  // namespace libmems
