#include "tlbmc/hal/fru_scanner_i2c.h"

#include <endian.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <sys/ioctl.h>
#include <unistd.h>

#include <array>
#include <cerrno>
#include <charconv>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <iomanip>
#include <ios>
#include <memory>
#include <optional>
#include <sstream>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "apifs/apifs.h"
#include "io/smbus/smbus.h"
#include "g3/macros.h"
#include "tlbmc/hal/fru_scanner.h"
#include "tlbmc/utils/fru_reader.h"
#include "tlbmc/utils/fru_utils.h"
#include "re2/re2.h"

namespace milotic_tlbmc {

using SmbusLocation = ecclesia::SmbusLocation;

namespace {

namespace fs = std::filesystem;

// Regex to extract the address from i2c file path.
// Example: /sys/bus/i2c/devices/i2c-12/12-0050 -> 0050
constexpr LazyRE2 kAddressRegex = {".+\\d+-([0-9abcdef]+$)"};

absl::StatusOr<absl::flat_hash_set<int>> GetI2cBusList(
    absl::string_view dir_path) {
  absl::flat_hash_set<int> bus_list;
  ecclesia::ApifsDirectory apifs((std::string(dir_path)));
  ECCLESIA_ASSIGN_OR_RETURN(auto entries, apifs.ListEntryPaths());
  for (const auto& entry : entries) {
    auto iter = entry.find("i2c-");
    if (iter == std::string::npos) {
      continue;
    }
    std::string bus_string = entry.substr(iter + 4);
    int bus = 0;
    if (!absl::SimpleAtoi(bus_string, &bus)) {
      return absl::InternalError("Failed to convert bus string to int");
    }
    bus_list.insert(bus);
  }
  if (bus_list.empty()) {
    return absl::InternalError("No i2c buses found in directory");
  }
  return bus_list;
}

int64_t ReadFromEeprom(int fd, off_t offset, size_t len, uint8_t* buf) {
  auto result = lseek(fd, offset, SEEK_SET);
  if (result < 0) {
    LOG(ERROR) << "Failed to seek to offset " << offset << " in eeprom file";
    return -1;
  };
  return read(fd, buf, len);
}

std::string GetEepromPath(size_t bus, size_t address,
                          absl::string_view root_dir) {
  std::stringstream output;
  output << root_dir << "/sys/bus/i2c/devices/" << bus << "-" << std::right
         << std::setfill('0') << std::setw(4) << std::hex << address
         << "/eeprom";
  return output.str();
}

std::vector<uint8_t> ProcessEeprom(int bus, size_t address,
                                   absl::string_view root_dir) {
  auto path = GetEepromPath(bus, address, root_dir);
  int file = open(path.c_str(), O_RDONLY);
  if (file < 0) {
    LOG(ERROR) << "Failed to open eeprom file: " << path << " "
               << strerror(errno);
    return {};
  }

  std::string error_message = "eeprom at " + std::to_string(bus) + " address " +
                              std::to_string(address);
  FRUReader reader(
      [file](off_t offset, size_t length, uint8_t* outbuf) -> int64_t {
        absl::StatusOr<int64_t> bytes_read =
            ReadFromEeprom(file, offset, length, outbuf);
        if (!bytes_read.ok()) {
          return -1;
        }
        return bytes_read.value();
      });
  std::pair<std::vector<uint8_t>, bool> pair =
      readFRUContents(reader, error_message);
  close(file);
  if (!pair.second) {
    LOG(ERROR) << "Failed to read eeprom at " << bus << " address " << address;
    return {};
  }
  return pair.first;
}

int GetRootBus(size_t bus, absl::string_view root_dir) {
  auto ec = std::error_code();
  auto path = std::filesystem::read_symlink(
      std::filesystem::path(absl::StrCat(root_dir, "/sys/bus/i2c/devices/i2c-",
                                         bus, "/mux_device")),
      ec);
  if (ec) {
    return -1;
  }

  std::string filename = path.filename();
  auto bus_iter = filename.find('-');
  if (bus_iter == std::string::npos) {
    return -1;
  }

  int root_bus = 0;
  return absl::SimpleAtoi(filename.substr(0, bus_iter), &root_bus) ? root_bus
                                                                   : -1;
}

}  // namespace

std::pair<std::vector<uint8_t>, bool> FruScannerI2c::ReadFruContentsFromI2c(
    int i2c_bus, int address, absl::Duration delay_between_reads) {
  std::optional<SmbusLocation> location =
      SmbusLocation::TryMake(i2c_bus, address);
  if (!location.has_value()) {
    return {{}, false};
  }

  uint8_t data;
  // Probe to see if this address is valid
  if (!smbus_access_->ReceiveByte(*location, &data).ok()) {
    return {{}, false};
  }

  std::string error_message =
      absl::Substitute("i2c scan at $0 address $1", i2c_bus, address);
  FRUReader reader(
      [this, location, delay_between_reads](off_t offset, size_t length,
                                            uint8_t* outbuf) -> int64_t {
        DLOG(INFO) << "Reading from i2c at offset " << offset << " length "
                   << length;
        absl::Span<uint8_t> outbuf_span(outbuf, length);
        for (int i = 0; i < length; ++i) {
          // TODO(b/385740524): Add 16bit scanning logic
          absl::Status smbus_status = smbus_access_->Read8(
              *location, static_cast<int>(offset + i), &outbuf_span[i]);
          if (!smbus_status.ok()) {
            LOG(INFO) << "Smbus read at offset " << offset
                      << " failed: " << smbus_status;
            return static_cast<int64_t>(outbuf_span[i]);
          }

          if (delay_between_reads > absl::ZeroDuration()) {
            clock_->Sleep(delay_between_reads);
          }
        }
        return static_cast<int64_t>(length);
      });

  return readFRUContents(reader, error_message);
}

absl::StatusOr<std::unique_ptr<I2cFruInfo>> FruScannerI2c::GetI2cFruInfoFromBus(
    int bus, int address, absl::Duration delay_between_reads) {
  auto fru_info = std::make_unique<I2cFruInfo>();
  fru_info->bus = bus;
  fru_info->address = address;
  std::vector<uint8_t> device = ProcessEeprom(bus, address, root_dir_);
  // If we get a device, then we don't need to manually scan.
  if (!device.empty()) {
    fru_info->data = std::move(device);
    return fru_info;
  }
  return ScanDirectI2cFru(bus, address, delay_between_reads);
}

absl::StatusOr<std::unique_ptr<I2cFruInfo>> FruScannerI2c::ScanDirectI2cFru(
    int bus, int address, absl::Duration delay_between_reads) {
  std::pair<std::vector<uint8_t>, bool> pair =
      ReadFruContentsFromI2c(bus, address, delay_between_reads);
  if (!pair.second) {
    return absl::InternalError(
        absl::StrCat("Failed to read eeprom at ", bus, " address ", address));
  }

  auto fru_info = std::make_unique<I2cFruInfo>();
  fru_info->bus = bus;
  fru_info->address = address;
  fru_info->data = pair.first;
  return fru_info;
}

absl::flat_hash_set<size_t> FruScannerI2c::FindI2cEeproms(
    int i2cBus, const std::shared_ptr<DeviceMap>& devices,
    absl::string_view root_dir,
    const absl::flat_hash_set<size_t>& root_blocked_addresses,
    absl::flat_hash_set<size_t>& root_found_addresses) {
  absl::flat_hash_set<size_t> found_list;
  std::string path =
      absl::StrCat(root_dir, "/sys/bus/i2c/devices/i2c-", i2cBus);

  // For each file listed under the i2c device
  // NOTE: This should be faster than just checking for each possible address
  // path.
  auto ec = std::error_code();
  for (const auto& p : fs::directory_iterator(path, ec)) {
    if (ec) {
      LOG(ERROR) << "directory_iterator err " << ec.message();
      break;
    }
    const std::string node = p.path().string();
    std::string address_string;
    if (!RE2::PartialMatch(node, *kAddressRegex, &address_string)) {
      continue;
    }
    absl::string_view address_view(address_string);
    size_t address = 0;
    std::from_chars(address_view.begin(), address_view.end(), address, 16);

    if (root_blocked_addresses.contains(address) ||
        root_found_addresses.contains(address)) {
      continue;
    }

    const std::string eeprom = node + "/eeprom";

    if (!fs::exists(eeprom, ec)) {
      continue;
    }

    // There is an eeprom file at this address, it may have invalid
    // contents, but we found it.
    found_list.insert(address);

    std::vector<uint8_t> device = ProcessEeprom(i2cBus, address, root_dir);
    if (!device.empty()) {
      devices->emplace(address, device);
    }
  }

  // Scan every bus from 0x50 to 0x57 only
  // SoT:
  // https://source.corp.google.com/h/gbmc/codesearch/+/main:meta-gbmc-staging/recipes-phosphor/configuration/entity-manager/0002-fru_device-limit-the-fru-scan-range-to-0x50-0x57.patch?q=fru%20device%20limit%20the%20fru%20scan%20range
  for (int address = kI2cFruScanStart; address <= kI2cFruScanEnd; address++) {
    if (found_list.contains(address) ||
        root_blocked_addresses.contains(address) ||
        root_found_addresses.contains(address)) {
      continue;
    }

    std::pair<std::vector<uint8_t>, bool> pair =
        ReadFruContentsFromI2c(i2cBus, address, absl::ZeroDuration());

    if (!pair.second) {
      LOG(INFO) << "Failed to read eeprom at " << i2cBus << " address "
                << address;
      continue;
    }

    found_list.insert(address);
    devices->emplace(address, pair.first);
  }

  return found_list;
}

void FruScannerI2c::FindI2CDevices(const absl::flat_hash_set<int>& i2c_buses,
                                   BusMap& bus_map) {
  const absl::flat_hash_map<size_t, std::optional<absl::flat_hash_set<size_t>>>&
      bus_block_list = scan_context_.bus_block_list;
  DLOG(INFO) << "Scanning i2c buses! ";
  for (const auto& bus : i2c_buses) {
    // Will need to store all addresses in blocklist for a bus.
    // If this is an extended bus, need to skip addresses found at root bus and
    // inherit the root bus block list.
    // blocked_addresses: addresses that are blocked on this bus or root bus.
    // root_found_addresses: addresses that are found at root bus.
    absl::flat_hash_set<size_t> blocked_addresses;
    absl::flat_hash_set<size_t> root_found_addresses;

    if (scan_context_.fru_addresses_list.contains(bus)) {
      // Bus is a root bus that has already been scanned, continue
      continue;
    }
    auto bus_iter = bus_block_list.find(bus);
    if (bus_iter != bus_block_list.end()) {
      if (bus_iter->second == std::nullopt) {
        DLOG(INFO) << "Skipping blocked bus " << bus;
        continue;  // Skip blocked busses.
      }
      for (size_t address : *(bus_iter->second)) {
        DLOG(INFO) << "Adding blocked address " << address << " on bus " << bus;
        blocked_addresses.insert(address);
      }
    }

    int root_bus = GetRootBus(bus, root_dir_);
    if (root_bus >= 0) {
      auto root_bus_iter = bus_block_list.find(root_bus);
      if (root_bus_iter != bus_block_list.end()) {
        if (root_bus_iter->second != std::nullopt) {
          for (auto& root_address : *(root_bus_iter->second)) {
            DLOG(INFO) << "Skipping root address " << root_address;
            blocked_addresses.insert(root_address);
          }
        }
      }

      if (auto find_root_bus = scan_context_.fru_addresses_list.find(root_bus);
          find_root_bus != scan_context_.fru_addresses_list.end()) {
        root_found_addresses = find_root_bus->second;
      }
    }

    auto device = std::make_shared<DeviceMap>();
    DLOG(INFO) << "Scanning bus " << bus;
    if (root_bus >= 0 && scan_context_.fru_addresses_list.find(root_bus) ==
                             scan_context_.fru_addresses_list.end()) {
      // Root bus has not been scanned, scan it before extended bus.
      DLOG(INFO) << "Scanning root bus " << root_bus;
      auto root_device = std::make_shared<DeviceMap>();

      absl::flat_hash_set<size_t> root_found_list =
          FindI2cEeproms(root_bus, root_device, root_dir_,
                         blocked_addresses, root_found_addresses);
      bus_map.emplace(root_bus, std::move(root_device));
      scan_context_.fru_addresses_list[root_bus].insert(root_found_list.begin(),
                                                        root_found_list.end());
      root_found_addresses = root_found_list;
    }
    absl::flat_hash_set<size_t> found_list = FindI2cEeproms(
        bus, device, root_dir_, blocked_addresses, root_found_addresses);
    bus_map.emplace(bus, std::move(device));
    scan_context_.fru_addresses_list[bus].insert(found_list.begin(),
                                                 found_list.end());
  }
}

absl::StatusOr<std::vector<std::unique_ptr<I2cFruInfo>>>
FruScannerI2c::ScanAllI2cFrus() {
  ECCLESIA_ASSIGN_OR_RETURN(auto bus_list, GetI2cBusList(root_dir_ + "/dev"));
  BusMap bus_map;
  FindI2CDevices(bus_list, bus_map);
  std::vector<std::unique_ptr<I2cFruInfo>> i2c_frus;
  for (const auto& [bus, device_map] : bus_map) {
    for (const auto& [address, data] : *device_map) {
      auto fru_info = std::make_unique<I2cFruInfo>();
      fru_info->bus = bus;
      fru_info->address = address;
      fru_info->data = data;
      i2c_frus.push_back(std::move(fru_info));
    }
  }
  return i2c_frus;
}

std::unique_ptr<FruScannerI2c> FruScannerI2c::Create(const Options& options) {
  return absl::WrapUnique(new FruScannerI2c(
      options.root_dir, options.i2c_dev_dir, options.bus_block_list));
}

}  // namespace milotic_tlbmc
