// 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 "typecd/partner.h"

#include <string>

#include <base/files/file_enumerator.h>
#include <base/logging.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <re2/re2.h>

#include "typecd/pd_vdo_constants.h"

namespace {

constexpr char kPartnerAltModeRegex[] = R"(port(\d+)-partner.(\d+))";

}

namespace typecd {

Partner::Partner(const base::FilePath& syspath)
    : Peripheral(syspath, "Partner"),
      num_alt_modes_(-1),
      metrics_reported_(false) {
  // Search for all alt modes which were already registered prior to daemon
  // init.
  base::FileEnumerator iter(GetSysPath(), false,
                            base::FileEnumerator::DIRECTORIES);
  for (auto path = iter.Next(); !path.empty(); path = iter.Next())
    AddAltMode(path);

  SetNumAltModes(ParseNumAltModes());
}

bool Partner::AddAltMode(const base::FilePath& mode_syspath) {
  int port, index;
  if (!RE2::FullMatch(mode_syspath.BaseName().value(), kPartnerAltModeRegex,
                      &port, &index))
    return false;

  if (IsAltModePresent(index)) {
    LOG(INFO) << "Alt mode already registered for syspath "
              << mode_syspath.BaseName();
    return true;
  }

  auto alt_mode = AltMode::CreateAltMode(mode_syspath);
  if (!alt_mode) {
    LOG(ERROR) << "Error creating alt mode for syspath " << mode_syspath;
    return false;
  }

  alt_modes_.emplace(index, std::move(alt_mode));

  LOG(INFO) << "Added alt mode for port " << port << " index " << index;

  return true;
}

void Partner::RemoveAltMode(const base::FilePath& mode_syspath) {
  int port, index;
  if (!RE2::FullMatch(mode_syspath.BaseName().value(), kPartnerAltModeRegex,
                      &port, &index)) {
    LOG(ERROR) << "Couldn't parse alt mode index from syspath " << mode_syspath;
    return;
  }

  auto it = alt_modes_.find(index);
  if (it == alt_modes_.end()) {
    LOG(INFO) << "Trying to delete non-existent alt mode " << index;
    return;
  }

  alt_modes_.erase(it);

  LOG(INFO) << "Removed alt mode for port " << port << " index " << index;
}

bool Partner::IsAltModePresent(int index) {
  auto it = alt_modes_.find(index);
  if (it != alt_modes_.end()) {
    return true;
  }

  LOG(INFO) << "Alt mode not found at index " << index;
  return false;
}

void Partner::UpdatePDInfoFromSysfs() {
  if (GetNumAltModes() == -1)
    SetNumAltModes(ParseNumAltModes());
  UpdatePDIdentityVDOs();
  UpdatePDRevision();
}

int Partner::ParseNumAltModes() {
  auto path = GetSysPath().Append("number_of_alternate_modes");

  std::string val_str;
  if (!base::ReadFileToString(path, &val_str))
    return -1;

  base::TrimWhitespaceASCII(val_str, base::TRIM_TRAILING, &val_str);

  int num_altmodes;
  if (!base::StringToInt(val_str.c_str(), &num_altmodes)) {
    LOG(ERROR) << "Couldn't parse num_altmodes from string: " << val_str;
    return -1;
  }

  return num_altmodes;
}

AltMode* Partner::GetAltMode(int index) {
  if (!IsAltModePresent(index))
    return nullptr;

  return alt_modes_.find(index)->second.get();
}

bool Partner::DiscoveryComplete() {
  return num_alt_modes_ == alt_modes_.size();
}

PartnerTypeMetric Partner::GetPartnerTypeMetric() {
  bool usb4 = false;
  auto partner_cap = (GetProductTypeVDO1() >> kDeviceCapabilityBitOffset) &
                     kDeviceCapabilityMask;
  if (partner_cap & kDeviceCapabilityUSB4) {
    usb4 = true;
  }

  // Check for TBT/DP.
  bool tbt_present = false;
  bool dp_present = false;
  for (const auto& [index, mode] : alt_modes_) {
    if (mode->GetSVID() == kTBTAltModeVID)
      tbt_present = true;

    if ((mode->GetSVID() == kDPAltModeSID) && (mode->GetVDO() & kDPModeSnk))
      dp_present = true;
  }

  bool usb_present = false;
  // For situations where the device is a "regular" USB peripheral, try to
  // determine whether it at least supports anything other than billboard.
  auto product_type = (GetIdHeaderVDO() >> kIDHeaderVDOProductTypeBitOffset) &
                      kIDHeaderVDOProductTypeMask;
  if (product_type == kIDHeaderVDOProductTypeUFPPeripheral ||
      product_type == kIDHeaderVDOProductTypeUFPHub) {
    auto device_cap = (GetProductTypeVDO1() >> kDeviceCapabilityBitOffset) &
                      kDeviceCapabilityMask;
    if (device_cap != kDeviceCapabilityBillboard)
      usb_present = true;
  }

  // Determine whether it is a hub or peripheral.
  bool hub = false;
  bool peripheral = false;
  if (product_type == kIDHeaderVDOProductTypeUFPHub) {
    hub = true;
  } else if (product_type == kIDHeaderVDOProductTypeUFPPeripheral) {
    peripheral = true;
  } else if (product_type == kIDHeaderVDOProductTypeUFPAMA) {
    // If it's an Alternate Mode Adapter, we have to guess.
    // Check the AMA VDO. If only billboard is supported, we guess that it's a
    // peripheral. In all other cases, we consider it's a hub.
    auto usb_speed = GetProductTypeVDO1() & kAMAVDOUSBSpeedBitMask;
    if (usb_speed != kAMAVDOUSBSpeedBillboard)
      hub = true;
    else
      peripheral = true;
  }

  // Now that we have all the data, let's make a type selection.
  PartnerTypeMetric ret = PartnerTypeMetric::kOther;
  if (usb4) {
    if (hub)
      ret = PartnerTypeMetric::kUSB4Hub;
    else if (peripheral)
      ret = PartnerTypeMetric::kUSB4Peripheral;
  } else if (tbt_present && dp_present) {
    if (hub)
      ret = PartnerTypeMetric::kTBTDPAltHub;
    else if (peripheral)
      ret = PartnerTypeMetric::kTBTDPAltPeripheral;
  } else if (tbt_present) {
    if (hub)
      ret = PartnerTypeMetric::kTBTHub;
    else if (peripheral)
      ret = PartnerTypeMetric::kTBTPeripheral;
  } else if (dp_present) {
    if (hub)
      ret = PartnerTypeMetric::kDPAltHub;
    else if (peripheral)
      ret = PartnerTypeMetric::kDPAltPeripheral;
  } else if (usb_present) {
    if (hub)
      ret = PartnerTypeMetric::kUSBHub;
    else if (peripheral)
      ret = PartnerTypeMetric::kUSBPeripheral;
  }

  return ret;
}

void Partner::ReportMetrics(Metrics* metrics) {
  if (!metrics || metrics_reported_)
    return;

  metrics->ReportPartnerType(GetPartnerTypeMetric());

  metrics_reported_ = true;
}

}  // namespace typecd
