// Copyright (c) 2012 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 "wimax_manager/gdm_driver.h"

#include <string>
#include <utility>

#include <base/files/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/strings/utf_string_conversions.h>

#include "wimax_manager/device_dbus_adaptor.h"
#include "wimax_manager/gdm_device.h"
#include "wimax_manager/network.h"

using std::string;
using std::vector;
using std::wstring;

namespace wimax_manager {

namespace {

const size_t kMaxNumberOfDevices = 256;
const size_t kMaxNumberOfProfiles = 8;
const size_t kMaxNumberOfNetworks = 16;

const char kLogDirectory[] = "/var/log/gct";
const char kNonVolatileDirectory[] = "/var/cache/gct";
const char *const kInitalDirectoriesToCreate[] = {
  kLogDirectory, kNonVolatileDirectory
};

string GetDeviceStatusDescription(WIMAX_API_DEVICE_STATUS device_status) {
  switch (device_status) {
    case WIMAX_API_DEVICE_STATUS_UnInitialized:
      return "Uninitialized";
    case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
      return "RF off (both H/W and S/W)";
    case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
      return "RF off (via H/W switch)";
    case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
      return "RF off (via S/W switch)";
    case WIMAX_API_DEVICE_STATUS_Ready:
      return "Ready";
    case WIMAX_API_DEVICE_STATUS_Scanning:
      return "Scanning";
    case WIMAX_API_DEVICE_STATUS_Connecting:
      return "Connecting";
    case WIMAX_API_DEVICE_STATUS_Data_Connected:
      return "Connected";
    default:
      return "Invalid";
  }
}

DeviceStatus ConvertDeviceStatus(WIMAX_API_DEVICE_STATUS device_status) {
  switch (device_status) {
    case WIMAX_API_DEVICE_STATUS_RF_OFF_HW_SW:
    case WIMAX_API_DEVICE_STATUS_RF_OFF_HW:
    case WIMAX_API_DEVICE_STATUS_RF_OFF_SW:
      return kDeviceStatusDisabled;
    case WIMAX_API_DEVICE_STATUS_Ready:
      return kDeviceStatusReady;
    case WIMAX_API_DEVICE_STATUS_Scanning:
      return kDeviceStatusScanning;
    case WIMAX_API_DEVICE_STATUS_Connecting:
      return kDeviceStatusConnecting;
    case WIMAX_API_DEVICE_STATUS_Data_Connected:
      return kDeviceStatusConnected;
    default:
      return kDeviceStatusUninitialized;
  }
}

string GetConnectionProgressDescription(
    WIMAX_API_CONNECTION_PROGRESS_INFO connection_progress) {
  switch (connection_progress) {
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Ranging:
      return "Ranging";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_SBC:
      return "SBC";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_Device:
      return "Device authentication via EAP";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_EAP_authentication_User:
      return "User authentication via EAP";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_3_way_handshake:
      return "3-way handshake";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration:
      return "Registration";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_De_registration:
      return "De-registration";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registered:
      return "Registered";
    case WIMAX_API_DEVICE_CONNECTION_PROGRESS_Registration_DSX:
      return "Registration DSX";
    default:
      return "Invalid";
  }
}

string GetNetworkTypeDescription(NetworkType network_type) {
  switch (network_type) {
    case kNetworkHome:
      return "Home";
    case kNetworkPartner:
      return "Partner";
    case kNetworkRoamingParnter:
      return "Roaming partner";
    default:
      return "Unknown";
  }
}

NetworkType ConvertNetworkType(WIMAX_API_NETWORK_TYPE network_type) {
  switch (network_type) {
    case WIMAX_API_HOME:
      return kNetworkHome;
    case WIMAX_API_PARTNER:
      return kNetworkPartner;
    case WIMAX_API_ROAMING_PARTNER:
      return kNetworkRoamingParnter;
    default:
      return kNetworkUnknown;
  }
}

template <size_t N>
bool ConvertWideCharacterArrayToUTF8String(const wchar_t (&wide_char_array)[N],
                                           std::string *utf8_string) {
  // Check if the wide character array is NULL-terminated.
  if (wmemchr(wide_char_array, L'\0', N) == nullptr)
    return false;

  size_t wide_string_length = wcslen(wide_char_array);
  CHECK_LT(wide_string_length, N);

  return base::WideToUTF8(wide_char_array, wide_string_length, utf8_string);
}

}  // namespace

GdmDriver::GdmDriver(Manager *manager)
    : Driver(manager),
      api_handle_(nullptr) {
}

GdmDriver::~GdmDriver() {
  Finalize();
}

bool GdmDriver::Initialize() {
  CHECK(!api_handle_);

  LOG(INFO) << "Initializing GDM driver";

  if (!CreateInitialDirectories())
    return false;

  GCT_WIMAX_API_PARAM api_param;
  CHECK_LT(snprintf(api_param.nonvolatile_dir,
                    sizeof(api_param.nonvolatile_dir),
                    "%s",
                    kNonVolatileDirectory),
           static_cast<int>(sizeof(api_param.nonvolatile_dir)));
  CHECK_LT(snprintf(api_param.log_path,
                    sizeof(api_param.log_path),
                    "%s",
                    kLogDirectory),
           static_cast<int>(sizeof(api_param.log_path)));
  api_param.log_level = 1;
  GCT_API_RET ret =
      GAPI_Initialize(GCT_WIMAX_SDK_EMBEDDED_EAP_ENABLED, &api_param);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  ret = GAPI_WiMaxAPIOpen(&api_handle_, GCT_WIMAX_API_OPEN_MODE_NORMAL);
  if (ret != GCT_API_RET_SUCCESS) {
    GAPI_DeInitialize();
    api_handle_ = nullptr;
    return false;
  }

  return true;
}

bool GdmDriver::Finalize() {
  if (!api_handle_)
    return true;

  LOG(INFO) << "Finalizing GDM driver";

  bool success = true;
  GAPI_SetDebugLevel(api_handle_, GAPI_LOG_FLUSH_LEVEL, nullptr);
  GCT_API_RET ret = GAPI_WiMaxAPIClose(api_handle_);
  api_handle_ = nullptr;

  if (ret != GCT_API_RET_SUCCESS)
    success = false;

  ret = GAPI_DeInitialize();
  if (ret != GCT_API_RET_SUCCESS)
    success = false;

  return success;
}

bool GdmDriver::GetDevices(vector<std::unique_ptr<Device>> *devices) {
  CHECK(devices);

  WIMAX_API_HW_DEVICE_ID device_list[kMaxNumberOfDevices];
  uint32_t num_devices = static_cast<uint32_t>(arraysize(device_list));
  GCT_API_RET ret = GAPI_GetListDevice(api_handle_, device_list, &num_devices);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  VLOG(1) << "Number of devices: " << num_devices;
  for (size_t i = 0; i < num_devices; ++i) {
    uint8_t device_index = device_list[i].deviceIndex;
    string device_name;
    if (!ConvertWideCharacterArrayToUTF8String(device_list[i].deviceName,
                                               &device_name)) {
      LOG(ERROR) << base::StringPrintf(
          "Ignoring device with index %d due to invalid device name",
          device_index);
      continue;
    }

    VLOG(1) << base::StringPrintf("Found device '%s': index = %d",
                                  device_name.c_str(),
                                  device_index);

    std::unique_ptr<GdmDevice> device(new(std::nothrow) GdmDevice(
        manager(), device_index, device_name, AsWeakPtr()));
    CHECK(device);
    // The WiMAX device changes its MAC address to the actual value after the
    // firmware is loaded. Opening the device seems to be enough to trigger the
    // update of the MAC address. So open the device here before
    // Manager::ScanDevices() creates the device DBus objects.
    device->Open();
    devices->push_back(std::move(device));
  }
  return true;
}

bool GdmDriver::OpenDevice(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_WiMaxDeviceOpen(&device_id);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  WIMAX_API_DEVICE_INFO device_info;
  ret = GAPI_GetDeviceInformation(&device_id, &device_info);
  if (ret != GCT_API_RET_SUCCESS)
    return CloseDevice(device);

  ByteIdentifier mac_address(device_info.macAddress,
                             arraysize(device_info.macAddress));
  device->SetMACAddress(mac_address);

  LOG(INFO) << "Opened device '" << device->name()
            << "': MAC address = " << device->mac_address().GetHexString();
  return true;
}

bool GdmDriver::CloseDevice(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_WiMaxDeviceClose(&device_id);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::GetDeviceStatus(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  WIMAX_API_DEVICE_STATUS device_status;
  WIMAX_API_CONNECTION_PROGRESS_INFO connection_progress;
  GCT_API_RET ret =
      GAPI_GetDeviceStatus(&device_id, &device_status, &connection_progress);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  device->SetStatus(ConvertDeviceStatus(device_status));
  device->set_connection_progress(connection_progress);

  VLOG(1) << "Device '" << device->name()
          << "': status = '" << GetDeviceStatusDescription(device_status)
          << "', connection progress = '"
          << GetConnectionProgressDescription(connection_progress) << "'";
  return true;
}

bool GdmDriver::GetDeviceRFInfo(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RF_INFORM rf_info;
  GCT_API_RET ret = GAPI_GetRFInform(&device_id, &rf_info);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  ByteIdentifier base_station_id(rf_info.bsId, arraysize(rf_info.bsId));
  device->SetBaseStationId(base_station_id);
  device->set_frequency(rf_info.Frequency);

  device->set_cinr({Network::DecodeCINR(rf_info.CINR),
                    Network::DecodeCINR(rf_info.CINR2)});

  device->set_rssi({Network::DecodeRSSI(rf_info.RSSI),
                    Network::DecodeRSSI(rf_info.RSSI2)});

  device->UpdateRFInfo();
  return true;
}

bool GdmDriver::SetDeviceEAPParameters(GdmDevice *device,
                                       GCT_API_EAP_PARAM *eap_parameters) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_SetEap(&device_id, eap_parameters);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::AutoSelectProfileForDevice(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  WIMAX_API_PROFILE_INFO profile_list[kMaxNumberOfProfiles];
  uint32_t num_profiles = static_cast<uint32_t>(arraysize(profile_list));
  GCT_API_RET ret =
      GAPI_GetSelectProfileList(&device_id, profile_list, &num_profiles);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  LOG(INFO) << "Number of profiles: " << num_profiles;
  for (size_t i = 0; i < num_profiles; ++i) {
    string profile_name;
    if (ConvertWideCharacterArrayToUTF8String(profile_list[i].profileName,
                                              &profile_name)) {
      LOG(INFO) << base::StringPrintf("Found profile '%s': id = %d",
                profile_name.c_str(),
                profile_list[i].profileID);
    }
  }

  if (num_profiles == 0)
    return false;

  ret = GAPI_SetProfile(&device_id, profile_list[0].profileID);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::PowerOnDeviceRF(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_CmdControlPowerManagement(&device_id, WIMAX_API_RF_ON);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::PowerOffDeviceRF(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret =
      GAPI_CmdControlPowerManagement(&device_id, WIMAX_API_RF_OFF);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::SetScanInterval(GdmDevice *device, uint32_t interval) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_SetScanInterval(&device_id, interval);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::GetNetworksForDevice(GdmDevice *device,
                                     vector<NetworkRefPtr> *networks) {
  CHECK(networks);

  GDEV_ID device_id = GetDeviceId(device);
  WIMAX_API_NSP_INFO network_list[kMaxNumberOfNetworks];
  uint32_t num_networks = static_cast<uint32_t>(arraysize(network_list));
  GCT_API_RET ret = GAPI_GetNetworkList(&device_id, network_list,
                                        &num_networks);
  if (ret != GCT_API_RET_SUCCESS)
    return false;

  // After connected to a network, the NSP info returned by GAPI_GetNetworkList
  // no longer contains updated CINR and RSSI values. The following code works
  // around the issue by getting the CINR and RSSI values via GAPI_GetRFInform
  // when the device is in the connected state.
  bool use_link_info = false;
  int link_cinr = Network::kMinCINR;
  int link_rssi = Network::kMinRSSI;
  WIMAX_API_DEVICE_STATUS device_status;
  WIMAX_API_CONNECTION_PROGRESS_INFO connection_progress;
  ret = GAPI_GetDeviceStatus(&device_id, &device_status, &connection_progress);
  if (ret == GCT_API_RET_SUCCESS &&
      device_status == WIMAX_API_DEVICE_STATUS_Data_Connected) {
    GCT_API_RF_INFORM rf_info;
    ret = GAPI_GetRFInform(&device_id, &rf_info);
    if (ret == GCT_API_RET_SUCCESS) {
      use_link_info = true;
      link_cinr = Network::DecodeCINR(rf_info.CINR);
      link_rssi = Network::DecodeRSSI(rf_info.RSSI);
    }
  }

  VLOG(1) << "Number of networks: " << num_networks;
  for (size_t i = 0; i < num_networks; ++i) {
    uint32_t network_id = network_list[i].NSPid;
    string network_name;
    if (!ConvertWideCharacterArrayToUTF8String(network_list[i].NSPName,
                                               &network_name)) {
      LOG(ERROR) << base::StringPrintf(
          "Ignoring network with identifer %08x due to invalid network name",
          network_id);
      continue;
    }

    wstring network_name_wcs;
    if (!base::UTF8ToWide(network_name.c_str(), network_name.size(),
                          &network_name_wcs) ||
        (wcscmp(network_name_wcs.c_str(), network_list[i].NSPName) != 0)) {
      LOG(ERROR) << base::StringPrintf(
          "Ignoring network with identifer %08x "
          "due to conversation error of network name",
          network_id);
      continue;
    }

    NetworkType network_type = ConvertNetworkType(network_list[i].networkType);
    int network_cinr =
        use_link_info ? link_cinr : Network::DecodeCINR(network_list[i].CINR);
    int network_rssi =
        use_link_info ? link_rssi : Network::DecodeRSSI(network_list[i].RSSI);
    LOG(INFO) << base::StringPrintf(
        "Found network '%s': type = '%s', id = %08x, CINR = %d, RSSI = %d",
        network_name.c_str(), GetNetworkTypeDescription(network_type).c_str(),
        network_id, network_cinr, network_rssi);

    NetworkRefPtr network = new(std::nothrow) Network(
        network_id, network_name, network_type, network_cinr, network_rssi);
    CHECK(network);
    networks->push_back(network);
  }
  return true;
}

bool GdmDriver::ConnectDeviceToNetwork(GdmDevice *device,
                                       const Network &network) {
  GDEV_ID device_id = GetDeviceId(device);
  wstring network_name_wcs;
  if (!base::UTF8ToWide(network.name().c_str(), network.name().size(),
                        &network_name_wcs)) {
    return false;
  }

  GCT_API_RET ret =
      GAPI_CmdConnectToNetwork(&device_id,
                               const_cast<wchar_t *>(network_name_wcs.c_str()),
                               0);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::DisconnectDeviceFromNetwork(GdmDevice *device) {
  GDEV_ID device_id = GetDeviceId(device);
  GCT_API_RET ret = GAPI_CmdDisconnectFromNetwork(&device_id);
  return ret == GCT_API_RET_SUCCESS;
}

bool GdmDriver::CreateInitialDirectories() const {
  for (const char *directory : kInitalDirectoriesToCreate) {
    if (!base::CreateDirectory(base::FilePath(directory))) {
      LOG(ERROR) << "Failed to create directory '" << directory << "'";
      return false;
    }
  }
  return true;
}

GDEV_ID GdmDriver::GetDeviceId(const GdmDevice *device) const {
  CHECK(device);

  GDEV_ID device_id;
  device_id.apiHandle = api_handle_;
  device_id.deviceIndex = device->index();
  return device_id;
}

}  // namespace wimax_manager
