// 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 <base/file_util.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/strings/utf_string_conversions.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 InitalDirectoriesToCreate[] = {
  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) == NULL)
    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_(NULL) {
}

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

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

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

  if (!CreateInitialDirectories())
    return false;

  GCT_WIMAX_API_PARAM api_param;
  strcpy(api_param.nonvolatile_dir, kNonVolatileDirectory);
  strcpy(api_param.log_path, kLogDirectory);
  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_ = NULL;
    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, NULL);
  GCT_API_RET ret = GAPI_WiMaxAPIClose(api_handle_);
  api_handle_ = NULL;

  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<Device *> *devices) {
  CHECK(devices);

  WIMAX_API_HW_DEVICE_ID device_list[kMaxNumberOfDevices];
  uint32 num_devices = static_cast<uint32>(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 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);

    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(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);

  vector<int> cinr;
  cinr.push_back(Network::DecodeCINR(rf_info.CINR));
  cinr.push_back(Network::DecodeCINR(rf_info.CINR2));
  device->set_cinr(cinr);

  vector<int> rssi;
  rssi.push_back(Network::DecodeRSSI(rf_info.RSSI));
  rssi.push_back(Network::DecodeRSSI(rf_info.RSSI2));
  device->set_rssi(rssi);

  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 num_profiles = static_cast<uint32>(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 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 num_networks = static_cast<uint32>(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 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 (size_t i = 0; i < arraysize(InitalDirectoriesToCreate); ++i) {
    const char *directory = InitalDirectoriesToCreate[i];
    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
