// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions 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 "libcef/browser/file_dialog_manager.h"

#include <utility>

#include "include/cef_dialog_handler.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/thread_util.h"

#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/file_chooser_file_info.h"
#include "net/base/directory_lister.h"

namespace {

class CefFileDialogCallbackImpl : public CefFileDialogCallback {
 public:
  using CallbackType = CefFileDialogRunner::RunFileChooserCallback;

  explicit CefFileDialogCallbackImpl(CallbackType callback)
      : callback_(std::move(callback)) {}

  ~CefFileDialogCallbackImpl() override {
    if (!callback_.is_null()) {
      // The callback is still pending. Cancel it now.
      if (CEF_CURRENTLY_ON_UIT()) {
        CancelNow(std::move(callback_));
      } else {
        CEF_POST_TASK(CEF_UIT,
                      base::BindOnce(&CefFileDialogCallbackImpl::CancelNow,
                                     std::move(callback_)));
      }
    }
  }

  void Continue(int selected_accept_filter,
                const std::vector<CefString>& file_paths) override {
    if (CEF_CURRENTLY_ON_UIT()) {
      if (!callback_.is_null()) {
        std::vector<base::FilePath> vec;
        if (!file_paths.empty()) {
          std::vector<CefString>::const_iterator it = file_paths.begin();
          for (; it != file_paths.end(); ++it)
            vec.push_back(base::FilePath(*it));
        }
        std::move(callback_).Run(selected_accept_filter, vec);
      }
    } else {
      CEF_POST_TASK(CEF_UIT,
                    base::BindOnce(&CefFileDialogCallbackImpl::Continue, this,
                                   selected_accept_filter, file_paths));
    }
  }

  void Cancel() override {
    if (CEF_CURRENTLY_ON_UIT()) {
      if (!callback_.is_null()) {
        CancelNow(std::move(callback_));
      }
    } else {
      CEF_POST_TASK(CEF_UIT,
                    base::BindOnce(&CefFileDialogCallbackImpl::Cancel, this));
    }
  }

  CallbackType Disconnect() WARN_UNUSED_RESULT { return std::move(callback_); }

 private:
  static void CancelNow(CallbackType callback) {
    CEF_REQUIRE_UIT();
    std::vector<base::FilePath> file_paths;
    std::move(callback).Run(0, file_paths);
  }

  CallbackType callback_;

  IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl);
};

void RunFileDialogDismissed(CefRefPtr<CefRunFileDialogCallback> callback,
                            int selected_accept_filter,
                            const std::vector<base::FilePath>& file_paths) {
  std::vector<CefString> paths;
  if (file_paths.size() > 0) {
    for (size_t i = 0; i < file_paths.size(); ++i)
      paths.push_back(file_paths[i].value());
  }
  callback->OnFileDialogDismissed(selected_accept_filter, paths);
}

class UploadFolderHelper
    : public net::DirectoryLister::DirectoryListerDelegate {
 public:
  explicit UploadFolderHelper(
      CefFileDialogRunner::RunFileChooserCallback callback)
      : callback_(std::move(callback)) {}

  ~UploadFolderHelper() override {
    if (!callback_.is_null()) {
      if (CEF_CURRENTLY_ON_UIT()) {
        CancelNow(std::move(callback_));
      } else {
        CEF_POST_TASK(CEF_UIT, base::BindOnce(&UploadFolderHelper::CancelNow,
                                              std::move(callback_)));
      }
    }
  }

  void OnListFile(
      const net::DirectoryLister::DirectoryListerData& data) override {
    CEF_REQUIRE_UIT();
    if (!data.info.IsDirectory())
      select_files_.push_back(data.path);
  }

  void OnListDone(int error) override {
    CEF_REQUIRE_UIT();
    if (!callback_.is_null()) {
      std::move(callback_).Run(0, select_files_);
    }
  }

 private:
  static void CancelNow(CefFileDialogRunner::RunFileChooserCallback callback) {
    CEF_REQUIRE_UIT();
    std::vector<base::FilePath> file_paths;
    std::move(callback).Run(0, file_paths);
  }

  CefFileDialogRunner::RunFileChooserCallback callback_;
  std::vector<base::FilePath> select_files_;

  DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
};

}  // namespace

CefFileDialogManager::CefFileDialogManager(
    CefBrowserHostImpl* browser,
    std::unique_ptr<CefFileDialogRunner> runner)
    : browser_(browser),
      runner_(std::move(runner)),
      file_chooser_pending_(false),
      weak_ptr_factory_(this) {}

CefFileDialogManager::~CefFileDialogManager() {}

void CefFileDialogManager::Destroy() {
  DCHECK(!file_chooser_pending_);
  runner_.reset(nullptr);
}

void CefFileDialogManager::RunFileDialog(
    cef_file_dialog_mode_t mode,
    const CefString& title,
    const CefString& default_file_path,
    const std::vector<CefString>& accept_filters,
    int selected_accept_filter,
    CefRefPtr<CefRunFileDialogCallback> callback) {
  DCHECK(callback.get());
  if (!callback.get())
    return;

  CefFileDialogRunner::FileChooserParams params;
  switch (mode & FILE_DIALOG_TYPE_MASK) {
    case FILE_DIALOG_OPEN:
      params.mode = blink::mojom::FileChooserParams::Mode::kOpen;
      break;
    case FILE_DIALOG_OPEN_MULTIPLE:
      params.mode = blink::mojom::FileChooserParams::Mode::kOpenMultiple;
      break;
    case FILE_DIALOG_OPEN_FOLDER:
      params.mode = blink::mojom::FileChooserParams::Mode::kUploadFolder;
      break;
    case FILE_DIALOG_SAVE:
      params.mode = blink::mojom::FileChooserParams::Mode::kSave;
      break;
  }

  DCHECK_GE(selected_accept_filter, 0);
  params.selected_accept_filter = selected_accept_filter;

  params.overwriteprompt = !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG);
  params.hidereadonly = !!(mode & FILE_DIALOG_HIDEREADONLY_FLAG);

  params.title = title;
  if (!default_file_path.empty())
    params.default_file_name = base::FilePath(default_file_path);

  if (!accept_filters.empty()) {
    std::vector<CefString>::const_iterator it = accept_filters.begin();
    for (; it != accept_filters.end(); ++it)
      params.accept_types.push_back(*it);
  }

  RunFileChooser(params, base::Bind(RunFileDialogDismissed, callback));
}

void CefFileDialogManager::RunFileChooser(
    std::unique_ptr<content::FileSelectListener> listener,
    const blink::mojom::FileChooserParams& params) {
  CEF_REQUIRE_UIT();

  CefFileDialogRunner::FileChooserParams cef_params;
  static_cast<blink::mojom::FileChooserParams&>(cef_params) = params;

  CefFileDialogRunner::RunFileChooserCallback callback;
  if (params.mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
    callback = base::BindOnce(
        &CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback,
        weak_ptr_factory_.GetWeakPtr(), params.mode, std::move(listener));
  } else {
    callback = base::BindOnce(
        &CefFileDialogManager::OnRunFileChooserDelegateCallback,
        weak_ptr_factory_.GetWeakPtr(), params.mode, std::move(listener));
  }

  RunFileChooserInternal(cef_params, std::move(callback));
}

void CefFileDialogManager::RunFileChooser(
    const CefFileDialogRunner::FileChooserParams& params,
    CefFileDialogRunner::RunFileChooserCallback callback) {
  CefFileDialogRunner::RunFileChooserCallback host_callback =
      base::BindOnce(&CefFileDialogManager::OnRunFileChooserCallback,
                     weak_ptr_factory_.GetWeakPtr(), std::move(callback));
  RunFileChooserInternal(params, std::move(host_callback));
}

void CefFileDialogManager::RunFileChooserInternal(
    const CefFileDialogRunner::FileChooserParams& params,
    CefFileDialogRunner::RunFileChooserCallback callback) {
  CEF_REQUIRE_UIT();

  if (file_chooser_pending_) {
    // Dismiss the new dialog immediately.
    std::move(callback).Run(0, std::vector<base::FilePath>());
    return;
  }

  file_chooser_pending_ = true;

  bool handled = false;

  if (browser_->client().get()) {
    CefRefPtr<CefDialogHandler> handler =
        browser_->client()->GetDialogHandler();
    if (handler.get()) {
      int mode = FILE_DIALOG_OPEN;
      switch (params.mode) {
        case blink::mojom::FileChooserParams::Mode::kOpen:
          mode = FILE_DIALOG_OPEN;
          break;
        case blink::mojom::FileChooserParams::Mode::kOpenMultiple:
          mode = FILE_DIALOG_OPEN_MULTIPLE;
          break;
        case blink::mojom::FileChooserParams::Mode::kUploadFolder:
          mode = FILE_DIALOG_OPEN_FOLDER;
          break;
        case blink::mojom::FileChooserParams::Mode::kSave:
          mode = FILE_DIALOG_SAVE;
          break;
        default:
          NOTREACHED();
          break;
      }

      if (params.overwriteprompt)
        mode |= FILE_DIALOG_OVERWRITEPROMPT_FLAG;
      if (params.hidereadonly)
        mode |= FILE_DIALOG_HIDEREADONLY_FLAG;

      std::vector<base::string16>::const_iterator it;

      std::vector<CefString> accept_filters;
      it = params.accept_types.begin();
      for (; it != params.accept_types.end(); ++it)
        accept_filters.push_back(*it);

      CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
          new CefFileDialogCallbackImpl(std::move(callback)));
      handled = handler->OnFileDialog(
          browser_, static_cast<cef_file_dialog_mode_t>(mode), params.title,
          params.default_file_name.value(), accept_filters,
          params.selected_accept_filter, callbackImpl.get());
      if (!handled) {
        // May return nullptr if the client has already executed the callback.
        callback = callbackImpl->Disconnect();
      }
    }
  }

  if (!handled && !callback.is_null()) {
    if (runner_.get()) {
      runner_->Run(browser_, params, std::move(callback));
    } else {
      LOG(WARNING) << "No file dialog runner available for this platform";
      std::move(callback).Run(0, std::vector<base::FilePath>());
    }
  }
}

void CefFileDialogManager::OnRunFileChooserCallback(
    CefFileDialogRunner::RunFileChooserCallback callback,
    int selected_accept_filter,
    const std::vector<base::FilePath>& file_paths) {
  CEF_REQUIRE_UIT();

  Cleanup();

  // Execute the callback asynchronously.
  CEF_POST_TASK(CEF_UIT, base::BindOnce(std::move(callback),
                                        selected_accept_filter, file_paths));
}

void CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback(
    const blink::mojom::FileChooserParams::Mode mode,
    std::unique_ptr<content::FileSelectListener> listener,
    int selected_accept_filter,
    const std::vector<base::FilePath>& file_paths) {
  CEF_REQUIRE_UIT();
  DCHECK_EQ(mode, blink::mojom::FileChooserParams::Mode::kUploadFolder);

  if (file_paths.size() == 0) {
    // Client canceled the file chooser.
    OnRunFileChooserDelegateCallback(mode, std::move(listener),
                                     selected_accept_filter, file_paths);
  } else {
    lister_.reset(new net::DirectoryLister(
        file_paths[0], net::DirectoryLister::NO_SORT_RECURSIVE,
        new UploadFolderHelper(base::BindOnce(
            &CefFileDialogManager::OnRunFileChooserDelegateCallback,
            weak_ptr_factory_.GetWeakPtr(), mode, std::move(listener)))));
    lister_->Start();
  }
}

void CefFileDialogManager::OnRunFileChooserDelegateCallback(
    blink::mojom::FileChooserParams::Mode mode,
    std::unique_ptr<content::FileSelectListener> listener,
    int selected_accept_filter,
    const std::vector<base::FilePath>& file_paths) {
  CEF_REQUIRE_UIT();

  base::FilePath base_dir;
  std::vector<blink::mojom::FileChooserFileInfoPtr> selected_files;

  if (!file_paths.empty()) {
    if (mode == blink::mojom::FileChooserParams::Mode::kUploadFolder) {
      base_dir = file_paths[0].DirName();
    }

    // Convert FilePath list to SelectedFileInfo list.
    for (size_t i = 0; i < file_paths.size(); ++i) {
      auto info = blink::mojom::FileChooserFileInfo::NewNativeFile(
          blink::mojom::NativeFileInfo::New(file_paths[i], base::string16()));
      selected_files.push_back(std::move(info));
    }
  }

  listener->FileSelected(std::move(selected_files), base_dir, mode);

  Cleanup();
}

void CefFileDialogManager::Cleanup() {
  if (lister_)
    lister_.reset();

  file_chooser_pending_ = false;
}
