/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "peripheral_manager_client.h"

#include <base/logging.h>

namespace android {

PeripheralManagerClient::PeripheralManagerClient() {}
PeripheralManagerClient::~PeripheralManagerClient() {}

Status PeripheralManagerClient::ListGpio(std::vector<std::string>* gpios) {
  *gpios = GpioManager::GetGpioManager()->GetGpioPins();
  return Status::ok();
}

Status PeripheralManagerClient::OpenGpio(const std::string& name) {
  if (!GpioManager::GetGpioManager()->HasGpio(name))
    return Status::fromServiceSpecificError(ENODEV);

  auto gpio = GpioManager::GetGpioManager()->OpenGpioPin(name);
  if (!gpio) {
    LOG(ERROR) << "Failed to open GPIO " << name;
    return Status::fromServiceSpecificError(EBUSY);
  }

  gpios_.emplace(name, std::move(gpio));
  return Status::ok();
}

Status PeripheralManagerClient::ReleaseGpio(const std::string& name) {
  gpios_.erase(name);
  return Status::ok();
}

Status PeripheralManagerClient::SetGpioEdge(const std::string& name, int type) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->SetEdgeType(GpioEdgeType(type)))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SetGpioActiveType(const std::string& name,
                                                  int type) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->SetActiveType(GpioActiveType(type)))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SetGpioDirection(const std::string& name,
                                                 int direction) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->SetDirection(GpioDirection(direction)))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SetGpioValue(const std::string& name,
                                             bool value) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->SetValue(value))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::GetGpioValue(const std::string& name,
                                             bool* value) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->GetValue(value))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::GetGpioPollingFd(
    const std::string& name,
    ::android::base::unique_fd* fd) {
  if (!gpios_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (gpios_.find(name)->second->GetPollingFd(fd))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::ListSpiBuses(std::vector<std::string>* buses) {
  *buses = SpiManager::GetSpiManager()->GetSpiDevBuses();
  return Status::ok();
}

Status PeripheralManagerClient::OpenSpiDevice(const std::string& name) {
  if (!SpiManager::GetSpiManager()->HasSpiDevBus(name))
    return Status::fromServiceSpecificError(ENODEV);

  std::unique_ptr<SpiDevice> device =
      SpiManager::GetSpiManager()->OpenSpiDevice(name);

  if (!device) {
    LOG(ERROR) << "Failed to open device " << name;
    return Status::fromServiceSpecificError(EBUSY);
  }

  spi_devices_.emplace(name, std::move(device));
  return Status::ok();
}

Status PeripheralManagerClient::ReleaseSpiDevice(const std::string& name) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  spi_devices_.erase(name);
  return Status::ok();
}

Status PeripheralManagerClient::SpiDeviceWriteByte(const std::string& name,
                                                   int8_t byte) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (spi_devices_.find(name)->second->WriteByte(byte))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceWriteBuffer(
    const std::string& name,
    const std::vector<uint8_t>& buffer) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (spi_devices_.find(name)->second->WriteBuffer(buffer.data(),
                                                   buffer.size()))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceTransfer(
    const std::string& name,
    const std::unique_ptr<std::vector<uint8_t>>& tx_data,
    std::unique_ptr<std::vector<uint8_t>>* rx_data,
    int size) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (!rx_data) {
    if (spi_devices_.find(name)->second->Transfer(tx_data->data(), nullptr,
                                                  size)) {
      return Status::ok();
    }
  } else {
    rx_data->reset(new std::vector<uint8_t>(size));
    if (spi_devices_.find(name)->second->Transfer(tx_data->data(),
                                                  (*rx_data)->data(), size)) {
      return Status::ok();
    }
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceSetMode(const std::string& name,
                                                 int mode) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (spi_devices_.find(name)->second->SetMode(SpiMode(mode)))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceSetFrequency(const std::string& name,
                                                      int frequency_hz) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (frequency_hz > 0 &&
      spi_devices_.find(name)->second->SetFrequency(frequency_hz))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceSetBitJustification(
    const std::string& name,
    bool lsb_first) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (spi_devices_.find(name)->second->SetBitJustification(lsb_first))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceSetBitsPerWord(const std::string& name,
                                                        int nbits) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (spi_devices_.find(name)->second->SetBitsPerWord(nbits))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::SpiDeviceSetDelay(const std::string& name,
                                                  int delay_usecs) {
  if (!spi_devices_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  // |delay_usecs| must be positive and fit in an unsigned 16 bit.
  if (delay_usecs < 0 || delay_usecs > INT16_MAX)
    return Status::fromServiceSpecificError(EINVAL);

  if (spi_devices_.find(name)->second->SetDelay(
          static_cast<uint16_t>(delay_usecs)))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::ListLeds(std::vector<std::string>* leds) {
  *leds = LedManager::GetLedManager()->GetLeds();
  return Status::ok();
}

Status PeripheralManagerClient::OpenLed(const std::string& name) {
  if (!LedManager::GetLedManager()->HasLed(name)) {
    return Status::fromServiceSpecificError(ENODEV);
  }
  auto led = LedManager::GetLedManager()->OpenLed(name);
  if (!led) {
    LOG(ERROR) << "Failed to open LED " << name;
    return Status::fromServiceSpecificError(EBUSY);
  }

  leds_.emplace(name, std::move(led));
  return Status::ok();
}

Status PeripheralManagerClient::ReleaseLed(const std::string& name) {
  leds_.erase(name);
  return Status::ok();
}

Status PeripheralManagerClient::LedGetBrightness(const std::string& name,
                                                 int* brightness) {
  if (!leds_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  uint32_t temp;
  if (leds_.find(name)->second->GetBrightness(&temp)) {
    *brightness = temp;
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::LedGetMaxBrightness(const std::string& name,
                                                    int* max_brightness) {
  if (!leds_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  uint32_t temp;
  if (leds_.find(name)->second->GetMaxBrightness(&temp)) {
    *max_brightness = temp;
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::LedSetBrightness(const std::string& name,
                                                 int brightness) {
  if (!leds_.count(name))
    return Status::fromServiceSpecificError(EPERM);

  if (leds_.find(name)->second->SetBrightness(brightness))
    return Status::ok();

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::ListI2cBuses(std::vector<std::string>* buses) {
  *buses = I2cManager::GetI2cManager()->GetI2cDevBuses();

  return Status::ok();
}

Status PeripheralManagerClient::OpenI2cDevice(const std::string& name,
                                              int32_t address) {
  if (!I2cManager::GetI2cManager()->HasI2cDevBus(name))
    return Status::fromServiceSpecificError(ENODEV);

  std::unique_ptr<I2cDevice> device =
      I2cManager::GetI2cManager()->OpenI2cDevice(name, address);

  if (!device) {
    LOG(ERROR) << "Failed to open device " << name;
    return Status::fromServiceSpecificError(EBUSY);
  }
  std::pair<std::string, uint32_t> i2c_dev(name, address);
  i2c_devices_.emplace(i2c_dev, std::move(device));
  return Status::ok();
}

Status PeripheralManagerClient::ReleaseI2cDevice(const std::string& name,
                                                 int32_t address) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  i2c_devices_.erase({name, address});
  return Status::ok();
}

Status PeripheralManagerClient::I2cRead(const std::string& name,
                                        int32_t address,
                                        std::vector<uint8_t>* data,
                                        int32_t size,
                                        int32_t* bytes_read) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  if (size < 0) {
    return Status::fromServiceSpecificError(EINVAL);
  }
  data->resize(size);

  uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read);
  int32_t ret = i2c_devices_.find({name, address})
                    ->second->Read(data->data(), data->size(), nread);
  data->resize(*nread);

  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
}

Status PeripheralManagerClient::I2cReadRegByte(const std::string& name,
                                               int32_t address,
                                               int32_t reg,
                                               int32_t* val) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  uint8_t tmp_val = 0;
  if (i2c_devices_.find({name, address})->second->ReadRegByte(reg, &tmp_val) ==
      0) {
    *val = tmp_val;
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::I2cReadRegWord(const std::string& name,
                                               int32_t address,
                                               int32_t reg,
                                               int32_t* val) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  uint16_t tmp_val = 0;
  if (i2c_devices_.find({name, address})->second->ReadRegWord(reg, &tmp_val) ==
      0) {
    *val = tmp_val;
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::I2cReadRegBuffer(const std::string& name,
                                                 int32_t address,
                                                 int32_t reg,
                                                 std::vector<uint8_t>* data,
                                                 int32_t size,
                                                 int32_t* bytes_read) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  if (size < 0) {
    return Status::fromServiceSpecificError(EINVAL);
  }
  data->resize(size);

  uint32_t* nread = reinterpret_cast<uint32_t*>(bytes_read);
  int32_t ret =
      i2c_devices_.find({name, address})
          ->second->ReadRegBuffer(reg, data->data(), data->size(), nread);

  data->resize(*nread);
  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
}

Status PeripheralManagerClient::I2cWrite(const std::string& name,
                                         int32_t address,
                                         const std::vector<uint8_t>& data,
                                         int32_t* bytes_written) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  int ret = i2c_devices_.find({name, address})
                ->second->Write(data.data(),
                                data.size(),
                                reinterpret_cast<uint32_t*>(bytes_written));

  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
}

Status PeripheralManagerClient::I2cWriteRegByte(const std::string& name,
                                                int32_t address,
                                                int32_t reg,
                                                int8_t val) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  if (i2c_devices_.find({name, address})->second->WriteRegByte(reg, val) == 0) {
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::I2cWriteRegWord(const std::string& name,
                                                int32_t address,
                                                int32_t reg,
                                                int32_t val) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  if (i2c_devices_.find({name, address})->second->WriteRegWord(reg, val) == 0) {
    return Status::ok();
  }

  return Status::fromServiceSpecificError(EREMOTEIO);
}

Status PeripheralManagerClient::I2cWriteRegBuffer(
    const std::string& name,
    int32_t address,
    int32_t reg,
    const std::vector<uint8_t>& data,
    int32_t* bytes_written) {
  if (!i2c_devices_.count({name, address}))
    return Status::fromServiceSpecificError(EPERM);

  int32_t ret =
      i2c_devices_.find({name, address})
          ->second->WriteRegBuffer(reg,
                                   data.data(),
                                   data.size(),
                                   reinterpret_cast<uint32_t*>(bytes_written));

  return ret == 0 ? Status::ok() : Status::fromServiceSpecificError(ret);
}

Status PeripheralManagerClient::ListUartDevices(
    std::vector<std::string>* devices) {
  *devices = UartManager::GetManager()->GetDevicesList();
  return Status::ok();
}

Status PeripheralManagerClient::OpenUartDevice(const std::string& name) {
  if (!UartManager::GetManager()->HasUartDevice(name))
    return Status::fromServiceSpecificError(ENODEV);

  auto uart_device = UartManager::GetManager()->OpenUartDevice(name);
  if (!uart_device) {
    LOG(ERROR) << "Failed to open UART device " << name;
    return Status::fromServiceSpecificError(EBUSY);
  }

  uart_devices_.emplace(name, std::move(uart_device));
  return Status::ok();
}

Status PeripheralManagerClient::ReleaseUartDevice(const std::string& name) {
  return uart_devices_.erase(name) ? Status::ok()
                                   : Status::fromServiceSpecificError(EPERM);
}

Status PeripheralManagerClient::SetUartDeviceBaudrate(const std::string& name,
                                                      int32_t baudrate) {
  auto uart_device = uart_devices_.find(name);
  if (uart_device == uart_devices_.end())
    return Status::fromServiceSpecificError(EPERM);

  if (baudrate < 0)
    return Status::fromServiceSpecificError(EINVAL);

  int ret = uart_device->second->SetBaudrate(static_cast<uint32_t>(baudrate));

  if (ret)
    return Status::fromServiceSpecificError(ret);

  return Status::ok();
}

Status PeripheralManagerClient::UartDeviceWrite(
    const std::string& name,
    const std::vector<uint8_t>& data,
    int32_t* bytes_written) {
  auto uart_device = uart_devices_.find(name);
  if (uart_device == uart_devices_.end())
    return Status::fromServiceSpecificError(EPERM);

  int ret = uart_device->second->Write(
      data, reinterpret_cast<uint32_t*>(bytes_written));

  if (ret)
    return Status::fromServiceSpecificError(ret);

  return Status::ok();
}

Status PeripheralManagerClient::UartDeviceRead(const std::string& name,
                                               std::vector<uint8_t>* data,
                                               int size,
                                               int* bytes_read) {
  auto uart_device = uart_devices_.find(name);
  if (uart_device == uart_devices_.end())
    return Status::fromServiceSpecificError(EPERM);

  int ret = uart_device->second->Read(
      data, size, reinterpret_cast<uint32_t*>(bytes_read));

  if (ret)
    return Status::fromServiceSpecificError(ret);

  return Status::ok();
}

}  // namespace android
