// Copyright 2013 The Flutter 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 "file_selector_plugin.h"

#include <comdef.h>
#include <comip.h>
#include <flutter/flutter_view.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <shobjidl.h>
#include <windows.h>

#include <cassert>
#include <memory>
#include <string>
#include <vector>

#include "file_dialog_controller.h"
#include "string_utils.h"

_COM_SMARTPTR_TYPEDEF(IEnumShellItems, IID_IEnumShellItems);
_COM_SMARTPTR_TYPEDEF(IFileDialog, IID_IFileDialog);
_COM_SMARTPTR_TYPEDEF(IShellItem, IID_IShellItem);
_COM_SMARTPTR_TYPEDEF(IShellItemArray, IID_IShellItemArray);

namespace file_selector_windows {

namespace {

using flutter::EncodableList;
using flutter::EncodableMap;
using flutter::EncodableValue;

// The kind of file dialog to show.
enum class DialogMode { open, save };

// Returns the path for |shell_item| as a UTF-8 string, or an
// empty string on failure.
std::string GetPathForShellItem(IShellItem* shell_item) {
  if (shell_item == nullptr) {
    return "";
  }
  wchar_t* wide_path = nullptr;
  if (!SUCCEEDED(shell_item->GetDisplayName(SIGDN_FILESYSPATH, &wide_path))) {
    return "";
  }
  std::string path = Utf8FromUtf16(wide_path);
  ::CoTaskMemFree(wide_path);
  return path;
}

// Implementation of FileDialogControllerFactory that makes standard
// FileDialogController instances.
class DefaultFileDialogControllerFactory : public FileDialogControllerFactory {
 public:
  DefaultFileDialogControllerFactory() {}
  virtual ~DefaultFileDialogControllerFactory() {}

  // Disallow copy and assign.
  DefaultFileDialogControllerFactory(
      const DefaultFileDialogControllerFactory&) = delete;
  DefaultFileDialogControllerFactory& operator=(
      const DefaultFileDialogControllerFactory&) = delete;

  std::unique_ptr<FileDialogController> CreateController(
      IFileDialog* dialog) const override {
    assert(dialog != nullptr);
    return std::make_unique<FileDialogController>(dialog);
  }
};

// Wraps an IFileDialog, managing object lifetime as a scoped object and
// providing a simplified API for interacting with it as needed for the plugin.
class DialogWrapper {
 public:
  explicit DialogWrapper(const FileDialogControllerFactory& dialog_factory,
                         IID type) {
    is_open_dialog_ = type == CLSID_FileOpenDialog;
    IFileDialogPtr dialog = nullptr;
    last_result_ = CoCreateInstance(type, nullptr, CLSCTX_INPROC_SERVER,
                                    IID_PPV_ARGS(&dialog));
    dialog_controller_ = dialog_factory.CreateController(dialog);
  }

  // Attempts to set the default folder for the dialog to |path|,
  // if it exists.
  void SetDefaultFolder(std::string_view path) {
    std::wstring wide_path = Utf16FromUtf8(path);
    IShellItemPtr item;
    last_result_ = SHCreateItemFromParsingName(wide_path.c_str(), nullptr,
                                               IID_PPV_ARGS(&item));
    if (!SUCCEEDED(last_result_)) {
      return;
    }
    dialog_controller_->SetDefaultFolder(item);
  }

  // Sets the file name that is initially shown in the dialog.
  void SetFileName(std::string_view name) {
    std::wstring wide_name = Utf16FromUtf8(name);
    last_result_ = dialog_controller_->SetFileName(wide_name.c_str());
  }

  // Sets the label of the confirmation button.
  void SetOkButtonLabel(std::string_view label) {
    std::wstring wide_label = Utf16FromUtf8(label);
    last_result_ = dialog_controller_->SetOkButtonLabel(wide_label.c_str());
  }

  // Adds the given options to the dialog's current option set.
  void AddOptions(FILEOPENDIALOGOPTIONS new_options) {
    FILEOPENDIALOGOPTIONS options;
    last_result_ = dialog_controller_->GetOptions(&options);
    if (!SUCCEEDED(last_result_)) {
      return;
    }
    options |= new_options;
    if (options & FOS_PICKFOLDERS) {
      opening_directory_ = true;
    }
    last_result_ = dialog_controller_->SetOptions(options);
  }

  // Sets the filters for allowed file types to select.
  void SetFileTypeFilters(const EncodableList& filters) {
    const std::wstring spec_delimiter = L";";
    const std::wstring file_wildcard = L"*.";
    std::vector<COMDLG_FILTERSPEC> filter_specs;
    // Temporary ownership of the constructed strings whose data is used in
    // filter_specs, so that they live until the call to SetFileTypes is done.
    std::vector<std::wstring> filter_names;
    std::vector<std::wstring> filter_extensions;
    filter_extensions.reserve(filters.size());
    filter_names.reserve(filters.size());

    for (const EncodableValue& filter_info_value : filters) {
      const auto& type_group = std::any_cast<TypeGroup>(
          std::get<flutter::CustomEncodableValue>(filter_info_value));
      filter_names.push_back(Utf16FromUtf8(type_group.label()));
      filter_extensions.push_back(L"");
      std::wstring& spec = filter_extensions.back();
      if (type_group.extensions().empty()) {
        spec += L"*.*";
      } else {
        for (const EncodableValue& extension : type_group.extensions()) {
          if (!spec.empty()) {
            spec += spec_delimiter;
          }
          spec +=
              file_wildcard + Utf16FromUtf8(std::get<std::string>(extension));
        }
      }
      filter_specs.push_back({filter_names.back().c_str(), spec.c_str()});
    }
    last_result_ = dialog_controller_->SetFileTypes(
        static_cast<UINT>(filter_specs.size()), filter_specs.data());
  }

  // Displays the dialog, and returns the selected files, or nullopt on error.
  std::optional<EncodableList> Show(HWND parent_window) {
    assert(dialog_controller_);
    last_result_ = dialog_controller_->Show(parent_window);
    if (!SUCCEEDED(last_result_)) {
      return std::nullopt;
    }

    EncodableList files;
    if (is_open_dialog_) {
      IShellItemArrayPtr shell_items;
      last_result_ = dialog_controller_->GetResults(&shell_items);
      if (!SUCCEEDED(last_result_)) {
        return std::nullopt;
      }
      IEnumShellItemsPtr item_enumerator;
      last_result_ = shell_items->EnumItems(&item_enumerator);
      if (!SUCCEEDED(last_result_)) {
        return std::nullopt;
      }
      IShellItemPtr shell_item;
      while (item_enumerator->Next(1, &shell_item, nullptr) == S_OK) {
        files.push_back(EncodableValue(GetPathForShellItem(shell_item)));
      }
    } else {
      IShellItemPtr shell_item;
      last_result_ = dialog_controller_->GetResult(&shell_item);
      if (!SUCCEEDED(last_result_)) {
        return std::nullopt;
      }
      files.push_back(EncodableValue(GetPathForShellItem(shell_item)));
    }
    return files;
  }

  // Returns the result of the last Win32 API call related to this object.
  HRESULT last_result() { return last_result_; }

 private:
  // The dialog controller that all interactions are mediated through, to allow
  // for unit testing.
  std::unique_ptr<FileDialogController> dialog_controller_;
  bool is_open_dialog_;
  bool opening_directory_ = false;
  HRESULT last_result_;
};

ErrorOr<flutter::EncodableList> ShowDialog(
    const FileDialogControllerFactory& dialog_factory, HWND parent_window,
    DialogMode mode, const SelectionOptions& options,
    const std::string* initial_directory, const std::string* suggested_name,
    const std::string* confirm_label) {
  IID dialog_type =
      mode == DialogMode::save ? CLSID_FileSaveDialog : CLSID_FileOpenDialog;
  DialogWrapper dialog(dialog_factory, dialog_type);
  if (!SUCCEEDED(dialog.last_result())) {
    return FlutterError("System error", "Could not create dialog",
                        EncodableValue(dialog.last_result()));
  }

  FILEOPENDIALOGOPTIONS dialog_options = 0;
  if (options.select_folders()) {
    dialog_options |= FOS_PICKFOLDERS;
  }
  if (options.allow_multiple()) {
    dialog_options |= FOS_ALLOWMULTISELECT;
  }
  if (dialog_options != 0) {
    dialog.AddOptions(dialog_options);
  }

  if (initial_directory) {
    dialog.SetDefaultFolder(*initial_directory);
  }
  if (suggested_name) {
    dialog.SetFileName(*suggested_name);
  }
  if (confirm_label) {
    dialog.SetOkButtonLabel(*confirm_label);
  }

  if (!options.allowed_types().empty()) {
    dialog.SetFileTypeFilters(options.allowed_types());
  }

  std::optional<EncodableList> files = dialog.Show(parent_window);
  if (!files) {
    if (dialog.last_result() != HRESULT_FROM_WIN32(ERROR_CANCELLED)) {
      return FlutterError("System error", "Could not show dialog",
                          EncodableValue(dialog.last_result()));
    } else {
      return EncodableList();
    }
  }
  return std::move(files.value());
}

// Returns the top-level window that owns |view|.
HWND GetRootWindow(flutter::FlutterView* view) {
  return ::GetAncestor(view->GetNativeWindow(), GA_ROOT);
}

}  // namespace

// static
void FileSelectorPlugin::RegisterWithRegistrar(
    flutter::PluginRegistrarWindows* registrar) {
  std::unique_ptr<FileSelectorPlugin> plugin =
      std::make_unique<FileSelectorPlugin>(
          [registrar] { return GetRootWindow(registrar->GetView()); },
          std::make_unique<DefaultFileDialogControllerFactory>());

  FileSelectorApi::SetUp(registrar->messenger(), plugin.get());
  registrar->AddPlugin(std::move(plugin));
}

FileSelectorPlugin::FileSelectorPlugin(
    FlutterRootWindowProvider window_provider,
    std::unique_ptr<FileDialogControllerFactory> dialog_controller_factory)
    : get_root_window_(std::move(window_provider)),
      controller_factory_(std::move(dialog_controller_factory)) {}

FileSelectorPlugin::~FileSelectorPlugin() = default;

ErrorOr<flutter::EncodableList> FileSelectorPlugin::ShowOpenDialog(
    const SelectionOptions& options, const std::string* initialDirectory,
    const std::string* confirmButtonText) {
  return ShowDialog(*controller_factory_, get_root_window_(), DialogMode::open,
                    options, initialDirectory, nullptr, confirmButtonText);
}

ErrorOr<flutter::EncodableList> FileSelectorPlugin::ShowSaveDialog(
    const SelectionOptions& options, const std::string* initialDirectory,
    const std::string* suggestedName, const std::string* confirmButtonText) {
  return ShowDialog(*controller_factory_, get_root_window_(), DialogMode::save,
                    options, initialDirectory, suggestedName,
                    confirmButtonText);
}

}  // namespace file_selector_windows
