// Copyright (c) 2012 The Chromium 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 "base/test/test_shortcut_win.h"

#include <windows.h>
#include <objbase.h>
#include <shlobj.h>
#include <propkey.h>
#include <wrl/client.h>

#include "base/files/file_path.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_propvariant.h"
#include "starboard/types.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace base {
namespace win {

void ValidatePathsAreEqual(const base::FilePath& expected_path,
                           const base::FilePath& actual_path) {
  wchar_t long_expected_path_chars[MAX_PATH] = {0};
  wchar_t long_actual_path_chars[MAX_PATH] = {0};

  // If |expected_path| is empty confirm immediately that |actual_path| is also
  // empty.
  if (expected_path.empty()) {
    EXPECT_TRUE(actual_path.empty());
    return;
  }

  // Proceed with LongPathName matching which will also confirm the paths exist.
  EXPECT_NE(0U, ::GetLongPathName(
      expected_path.value().c_str(), long_expected_path_chars, MAX_PATH))
          << "Failed to get LongPathName of " << expected_path.value();
  EXPECT_NE(0U, ::GetLongPathName(
      actual_path.value().c_str(), long_actual_path_chars, MAX_PATH))
          << "Failed to get LongPathName of " << actual_path.value();

  base::FilePath long_expected_path(long_expected_path_chars);
  base::FilePath long_actual_path(long_actual_path_chars);
  EXPECT_FALSE(long_expected_path.empty());
  EXPECT_FALSE(long_actual_path.empty());

  EXPECT_EQ(long_expected_path, long_actual_path);
}

void ValidateShortcut(const base::FilePath& shortcut_path,
                      const ShortcutProperties& properties) {
  Microsoft::WRL::ComPtr<IShellLink> i_shell_link;
  Microsoft::WRL::ComPtr<IPersistFile> i_persist_file;

  wchar_t read_target[MAX_PATH] = {0};
  wchar_t read_working_dir[MAX_PATH] = {0};
  wchar_t read_arguments[MAX_PATH] = {0};
  wchar_t read_description[MAX_PATH] = {0};
  wchar_t read_icon[MAX_PATH] = {0};
  int read_icon_index = 0;

  HRESULT hr;

  // Initialize the shell interfaces.
  EXPECT_TRUE(SUCCEEDED(hr = ::CoCreateInstance(CLSID_ShellLink, NULL,
                                                CLSCTX_INPROC_SERVER,
                                                IID_PPV_ARGS(&i_shell_link))));
  if (FAILED(hr))
    return;

  EXPECT_TRUE(
      SUCCEEDED(hr = i_shell_link.CopyTo(i_persist_file.GetAddressOf())));
  if (FAILED(hr))
    return;

  // Load the shortcut.
  EXPECT_TRUE(SUCCEEDED(hr = i_persist_file->Load(
      shortcut_path.value().c_str(), 0))) << "Failed to load shortcut at "
                                          << shortcut_path.value();
  if (FAILED(hr))
    return;

  if (properties.options & ShortcutProperties::PROPERTIES_TARGET) {
    EXPECT_TRUE(SUCCEEDED(
        i_shell_link->GetPath(read_target, MAX_PATH, NULL, SLGP_SHORTPATH)));
    ValidatePathsAreEqual(properties.target, base::FilePath(read_target));
  }

  if (properties.options & ShortcutProperties::PROPERTIES_WORKING_DIR) {
    EXPECT_TRUE(SUCCEEDED(
        i_shell_link->GetWorkingDirectory(read_working_dir, MAX_PATH)));
    ValidatePathsAreEqual(properties.working_dir,
                          base::FilePath(read_working_dir));
  }

  if (properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) {
    EXPECT_TRUE(SUCCEEDED(
        i_shell_link->GetArguments(read_arguments, MAX_PATH)));
    EXPECT_EQ(properties.arguments, read_arguments);
  }

  if (properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) {
    EXPECT_TRUE(SUCCEEDED(
        i_shell_link->GetDescription(read_description, MAX_PATH)));
    EXPECT_EQ(properties.description, read_description);
  }

  if (properties.options & ShortcutProperties::PROPERTIES_ICON) {
    EXPECT_TRUE(SUCCEEDED(
        i_shell_link->GetIconLocation(read_icon, MAX_PATH, &read_icon_index)));
    ValidatePathsAreEqual(properties.icon, base::FilePath(read_icon));
    EXPECT_EQ(properties.icon_index, read_icon_index);
  }

  Microsoft::WRL::ComPtr<IPropertyStore> property_store;
  EXPECT_TRUE(
      SUCCEEDED(hr = i_shell_link.CopyTo(property_store.GetAddressOf())));
  if (FAILED(hr))
    return;

  if (properties.options & ShortcutProperties::PROPERTIES_APP_ID) {
    ScopedPropVariant pv_app_id;
    EXPECT_EQ(S_OK, property_store->GetValue(PKEY_AppUserModel_ID,
                                             pv_app_id.Receive()));
    switch (pv_app_id.get().vt) {
      case VT_EMPTY:
        EXPECT_TRUE(properties.app_id.empty());
        break;
      case VT_LPWSTR:
        EXPECT_EQ(properties.app_id, pv_app_id.get().pwszVal);
        break;
      default:
        ADD_FAILURE() << "Unexpected variant type: " << pv_app_id.get().vt;
    }
  }

  if (properties.options & ShortcutProperties::PROPERTIES_DUAL_MODE) {
    ScopedPropVariant pv_dual_mode;
    EXPECT_EQ(S_OK, property_store->GetValue(PKEY_AppUserModel_IsDualMode,
                                             pv_dual_mode.Receive()));
    switch (pv_dual_mode.get().vt) {
      case VT_EMPTY:
        EXPECT_FALSE(properties.dual_mode);
        break;
      case VT_BOOL:
        EXPECT_EQ(properties.dual_mode,
                  static_cast<bool>(pv_dual_mode.get().boolVal));
        break;
      default:
        ADD_FAILURE() << "Unexpected variant type: " << pv_dual_mode.get().vt;
    }
  }
}

}  // namespace win
}  // namespace base
