// Copyright 2017 The Cobalt Authors. All Rights Reserved.
//
// 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 <stdlib.h>

#include <algorithm>
#include <string>
#include <vector>

#include "starboard/common/device_type.h"
#include "starboard/common/log.h"
#include "starboard/common/string.h"
#include "starboard/configuration_constants.h"
#include "starboard/memory.h"
#include "starboard/shared/uwp/application_uwp.h"
#include "starboard/shared/uwp/keys.h"
#include "starboard/shared/win32/wchar_utils.h"
#include "starboard/system.h"
#include "starboard/xb1/shared/internal_shims.h"
#include "starboard/xb1/system_properties.h"

using starboard::shared::win32::platformStringToString;
using Windows::Security::ExchangeActiveSyncProvisioning::
    EasClientDeviceInformation;
using Windows::System::Profile::AnalyticsInfo;
using Windows::System::Profile::AnalyticsVersionInfo;
using Windows::System::UserProfile::AdvertisingManager;

namespace {

#define arraysize(array) (sizeof(array) / sizeof(*array))

struct UwpDevice {
  const char* deviceForm;
  const char* chipsetModel;
  const char* model;
  const char* year;
} UwpDevices;

// Array of model name and year for known UWP devices.
struct UwpDevice kDevices[] = {
    {"Xbox One", "XboxOne", "XboxOne", "2013"},
    {"Xbox One S", "XboxOne", "XboxOne S", "2016"},
    {"Xbox One X", "XboxOne", "XboxOne X", "2017"},
    {"Xbox One X DevKit", "XboxOne", "XboxOne X", "2017"},
    {"Xbox Series X", "XboxScarlett", "XboxScarlett Series X", "2020"},
    {"Xbox Series X Devkit", "XboxScarlett", "XboxScarlett Series X", "2020"},
    {"Xbox Series S", "XboxScarlett", "XboxScarlett Series S", "2020"},
};

const char kSystemIntegrator[] = "YouTube";
const char kXboxDeviceFormField[] = "Xbox";

// Year for unknown Uwp devices. This assumes that they will be as
// capable as the most recent known device.
const char kUnknownModelYear[] = "2020";

// Chipset for unidentified device forms.
const char kUnknownChipset[] = "UwpUnknown";

bool CopyStringAndTestIfSuccess(char* out_value,
                                int value_length,
                                const char* from_value) {
  if (strlen(from_value) + 1 > value_length)
    return false;
  starboard::strlcpy(out_value, from_value, value_length);
  return true;
}

bool CopyStringAndTestIfSuccess(char* out_value,
                                int value_length,
                                const wchar_t* from_value) {
  char* from_value_str = new char[value_length];
  int len = wcstombs(from_value_str, from_value, value_length);
  bool result = len < 0 ? false
                        : CopyStringAndTestIfSuccess(out_value, value_length,
                                                     from_value_str);
  delete from_value_str;
  return result;
}

const std::size_t kOsVersionSize = 128;

struct WindowsVersion {
  uint16_t major_version;
  uint16_t minor_version;
  uint16_t build_version;
  uint16_t revision;
};

bool GetWindowsVersion(WindowsVersion* version) {
  SB_DCHECK(version);
  AnalyticsVersionInfo ^ version_info = AnalyticsInfo::VersionInfo;
  std::string device_family_version =
      platformStringToString(version_info->DeviceFamilyVersion);
  if (device_family_version.empty()) {
    return false;
  }
  uint64_t version_info_all =
      strtoull(device_family_version.c_str(), nullptr, 10);
  if (version_info_all == 0) {
    return false;
  }
  version->major_version = (version_info_all >> 48) & 0xFFFF;
  version->minor_version = (version_info_all >> 32) & 0xFFFF;
  version->build_version = (version_info_all >> 16) & 0xFFFF;
  version->revision = version_info_all & 0xFFFF;
  return true;
}

std::string GetDeviceForm() {
  Platform::String ^ device_form = AnalyticsInfo::DeviceForm;
  return platformStringToString(device_form);
}

bool GetBrandName(char* out_value, int value_length) {
  EasClientDeviceInformation ^ current_device_info =
      ref new EasClientDeviceInformation();
  std::string brand_name =
      platformStringToString(current_device_info->SystemManufacturer);
  if (brand_name.empty()) {
    return false;
  }
  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    brand_name.c_str());
}

bool GetChipsetModelNumber(char* out_value, int value_length) {
  std::string deviceForm = GetDeviceForm();
  // If the device form is a known device, return the chipset model from the
  // table.
  for (size_t i = 0; i < arraysize(kDevices); i++) {
    const UwpDevice* device = kDevices + i;
    if (deviceForm == device->deviceForm) {
      return CopyStringAndTestIfSuccess(out_value, value_length,
                                        device->chipsetModel);
    }
  }

  // The device form is not a known value, return unknown chipset.
  return CopyStringAndTestIfSuccess(out_value, value_length, kUnknownChipset);
}

bool GetFirmwareVersion(char* out_value, int value_length) {
  WindowsVersion version = {0};
  if (!GetWindowsVersion(&version)) {
    return false;
  }
  // The caller expects that the the output string will only be written if
  // when true is returned. Therefore we have to buffer the string in case
  // there is a false condition, such as small memory input size to hold
  // the output parameter.
  std::vector<char> out_path_copy(kSbFileMaxPath + 1, 0);
  int len = std::min<int>(kSbFileMaxPath, value_length);
  int return_value = SbStringFormatF(
      out_path_copy.data(), len, "%u.%u.%u.%u", version.major_version,
      version.minor_version, version.build_version, version.revision);

  const bool ok = ((return_value > 0) && (return_value < value_length));
  if (ok) {
    starboard::strlcpy(out_value, out_path_copy.data(), len);
  }
  return ok;
}

bool GetFriendlyName(char* out_value, int value_length) {
  EasClientDeviceInformation ^ current_device_info =
      ref new EasClientDeviceInformation();
  std::string friendly_name =
      platformStringToString(current_device_info->FriendlyName);
  if (friendly_name.empty()) {
    return false;
  }
  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    friendly_name.c_str());
}

bool GetModelYear(char* out_value, int value_length) {
  std::string deviceForm = GetDeviceForm();
  for (size_t i = 0; i < arraysize(kDevices); i++) {
    const UwpDevice* device = kDevices + i;
    if (deviceForm == device->deviceForm) {
      return CopyStringAndTestIfSuccess(out_value, value_length, device->year);
    }
  }

  return CopyStringAndTestIfSuccess(out_value, value_length, kUnknownModelYear);
}

bool GetModelName(char* out_value, int value_length) {
  std::string deviceForm = GetDeviceForm();
  for (size_t i = 0; i < arraysize(kDevices); i++) {
    const UwpDevice* device = kDevices + i;
    if (deviceForm == device->deviceForm) {
      return CopyStringAndTestIfSuccess(out_value, value_length, device->model);
    }
  }

  // The device form is not a known value, return the device form verbatim.
  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    deviceForm.c_str());
}

bool GetPlatformName(char* out_value, int value_length) {
  EasClientDeviceInformation ^ current_device_info =
      ref new EasClientDeviceInformation();
  std::string operating_system =
      platformStringToString(current_device_info->OperatingSystem);

  AnalyticsVersionInfo ^ version_info = AnalyticsInfo::VersionInfo;
  std::string os_name_and_version =
      platformStringToString(current_device_info->OperatingSystem);
  if (os_name_and_version.empty()) {
    return false;
  }

  WindowsVersion os_version;
  if (!GetWindowsVersion(&os_version)) {
    return false;
  }

  os_name_and_version += " ";
  char os_version_buffer[kOsVersionSize];
  os_version_buffer[0] = '\0';

  int return_value =
      SbStringFormatF(os_version_buffer, value_length, "%u.%u",
                      os_version.major_version, os_version.minor_version);
  if ((return_value < 0) || (return_value >= value_length)) {
    return false;
  }

  os_name_and_version.append(os_version_buffer);

  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    os_name_and_version.c_str());
}

bool GetAppXVersion(char* out_value, int value_length) {
  Windows::ApplicationModel::PackageVersion version =
      Windows::ApplicationModel::Package::Current->Id->Version;
  std::stringstream version_string;
  version_string << version.Major << '.' << version.Minor << '.'
                 << version.Build << '.' << version.Revision;
  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    version_string.str().c_str());
}

std::string GetAdvertisingId() {
  Platform::String ^ advertising_id = AdvertisingManager::AdvertisingId;
  return platformStringToString(advertising_id);
}

bool GetDeviceType(char* out_value, int value_length) {
  AnalyticsVersionInfo ^ version_info = AnalyticsInfo::VersionInfo;
  std::string family = starboard::shared::win32::platformStringToString(
      version_info->DeviceFamily);
  std::string device_type;
  if (family.compare("Windows.Desktop") == 0) {
    return CopyStringAndTestIfSuccess(out_value, value_length,
                                      starboard::kSystemDeviceTypeDesktopPC);
  }
  if (family.compare("Windows.Xbox") == 0) {
    return CopyStringAndTestIfSuccess(out_value, value_length,
                                      starboard::kSystemDeviceTypeGameConsole);
  }
  SB_NOTREACHED();
  return CopyStringAndTestIfSuccess(out_value, value_length,
                                    starboard::kSystemDeviceTypeUnknown);
}

}  // namespace

bool SbSystemGetProperty(SbSystemPropertyId property_id,
                         char* out_value,
                         int value_length) {
  if (!out_value || !value_length) {
    return false;
  }

  using starboard::shared::uwp::SpeechApiKey;

  switch (property_id) {
    case kSbSystemPropertyCertificationScope: {
      Platform::String ^ scope = starboard::xb1::shared::GetCertScope();
      if (scope->IsEmpty()) {
        if (kCertificationScope[0] == '\0')
          return false;
        return CopyStringAndTestIfSuccess(out_value, value_length,
                                          kCertificationScope);
      }
      bool result =
          CopyStringAndTestIfSuccess(out_value, value_length, scope->Data());
      return result;
    }
    case kSbSystemPropertyChipsetModelNumber:
      return GetChipsetModelNumber(out_value, value_length);
    case kSbSystemPropertyFirmwareVersion:
      return GetFirmwareVersion(out_value, value_length);
    case kSbSystemPropertyFriendlyName:
      return GetFriendlyName(out_value, value_length);
    case kSbSystemPropertyBrandName:
      return GetBrandName(out_value, value_length);
    case kSbSystemPropertyModelName:
      return GetModelName(out_value, value_length);
    case kSbSystemPropertyModelYear:
      return GetModelYear(out_value, value_length);
    case kSbSystemPropertySystemIntegratorName:
      return CopyStringAndTestIfSuccess(out_value, value_length,
                                        kSystemIntegrator);
    case kSbSystemPropertyPlatformName:
      return GetPlatformName(out_value, value_length);
    case kSbSystemPropertySpeechApiKey:
      CopyStringAndTestIfSuccess(out_value, value_length, SpeechApiKey());
      return true;
    case kSbSystemPropertyUserAgentAuxField:
      return GetAppXVersion(out_value, value_length);
#if SB_API_VERSION >= 14
    case kSbSystemPropertyAdvertisingId: {
      std::string advertising_id = GetAdvertisingId();
      return CopyStringAndTestIfSuccess(out_value, value_length,
                                        advertising_id.c_str());
    }
    case kSbSystemPropertyLimitAdTracking: {
      std::string advertising_id = GetAdvertisingId();
      // If we get an empty ID, that means the user disabled it.
      return CopyStringAndTestIfSuccess(out_value, value_length,
                                        advertising_id.empty() ? "1" : "0");
    }
#endif  // SB_API_VERSION >= 14
#if SB_API_VERSION >= 15
    case kSbSystemPropertyDeviceType:
      return GetDeviceType(out_value, value_length);
#endif
    default:
      SB_DLOG(WARNING) << __FUNCTION__
                       << ": Unrecognized property: " << property_id;
      break;
  }
  return false;
}
