// Copyright 2013 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 <atlbase.h>
#include <atlapp.h>  // NOLINT

#include "base/at_exit.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_pump_dispatcher.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/threading/thread.h"
#include "chrome/common/chrome_constants.h"
#include "cloud_print/common/win/cloud_print_utils.h"
#include "cloud_print/service/resources.h"
#include "cloud_print/service/service_state.h"
#include "cloud_print/service/win/chrome_launcher.h"
#include "cloud_print/service/win/service_controller.h"
#include "cloud_print/service/win/service_utils.h"
#include "cloud_print/service/win/setup_listener.h"

using cloud_print::LoadLocalString;
using cloud_print::GetErrorMessage;

class SetupDialog : public base::RefCounted<SetupDialog>,
                    public ATL::CDialogImpl<SetupDialog> {
 public:
  // Enables accelerators.
  class Dispatcher : public base::MessagePumpDispatcher {
   public:
    explicit Dispatcher(SetupDialog* dialog) : dialog_(dialog) {}
    ~Dispatcher() override {}

    // MessagePumpDispatcher:
    uint32_t Dispatch(const MSG& msg) override {
      MSG msg2 = msg;
      uint32_t action = POST_DISPATCH_NONE;
      if (!dialog_->IsDialogMessage(&msg2))
        action = POST_DISPATCH_PERFORM_DEFAULT;
      return action;
    }

   private:
    scoped_refptr<SetupDialog> dialog_;
  };

  typedef ATL::CDialogImpl<SetupDialog> Base;
  enum { IDD = IDD_SETUP_DIALOG };

  BEGIN_MSG_MAP(SetupDialog)
    MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
    MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnCtrColor)
    MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
    COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
    COMMAND_ID_HANDLER(IDC_START, OnStart)
    COMMAND_ID_HANDLER(IDC_INSTALL, OnInstall)
    COMMAND_ID_HANDLER(IDC_LOGGING, OnLogging)
  END_MSG_MAP()

  SetupDialog();

 private:
  friend class base::RefCounted<SetupDialog>;
  ~SetupDialog() override {}

  // Window Message Handlers
  LRESULT OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam,
                       BOOL& handled);
  LRESULT OnCtrColor(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);
  LRESULT OnCancel(UINT, INT nIdentifier, HWND, BOOL& handled);
  LRESULT OnStart(UINT, INT nIdentifier, HWND, BOOL& handled);
  LRESULT OnInstall(UINT, INT nIdentifier, HWND, BOOL& handled);
  LRESULT OnLogging(UINT, INT nIdentifier, HWND, BOOL& handled);
  LRESULT OnDestroy(UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);

  void PostUITask(const base::Closure& task);
  void PostIOTask(const base::Closure& task);

  // UI Calls.

  // Disables all controls after users actions.
  void DisableControls();
  // Updates state of controls after when we received service status.
  void SetState(ServiceController::State state, const base::string16& user,
                 bool is_logging_enabled);
  // Show message box with error.
  void ShowErrorMessageBox(const base::string16& error_message);
  // Show use message box instructions how to deal with opened Chrome window.
  void AskToCloseChrome();
  base::string16 GetDlgItemText(int id) const;
  base::string16 GetUser() const;
  base::string16 GetPassword() const;
  bool IsLoggingEnabled() const;
  bool IsInstalled() const {
    return state_ > ServiceController::STATE_NOT_FOUND;
  }

  // IO Calls.
  // Installs service.
  void Install(const base::string16& user, const base::string16& password,
               bool enable_logging);
  // Starts service.
  void Start();
  // Stops service.
  void Stop();
  // Uninstall service.
  void Uninstall();
  // Update service state.
  void UpdateState();
  // Posts task to UI thread to show error using string id.
  void ShowError(int string_id);
  // Posts task to UI thread to show error using string.
  void ShowError(const base::string16& error_message);
  // Posts task to UI thread to show error using error code.
  void ShowError(HRESULT hr);

  ServiceController::State state_;
  base::Thread worker_;

  base::MessageLoop* ui_loop_;
  base::MessageLoop* io_loop_;

  ServiceController controller_;
};

SetupDialog::SetupDialog()
    : state_(ServiceController::STATE_NOT_FOUND),
      worker_("worker") {
  ui_loop_ = base::MessageLoop::current();
  DCHECK(base::MessageLoopForUI::IsCurrent());

  worker_.StartWithOptions(
      base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
  io_loop_ = worker_.message_loop();
  DCHECK(io_loop_->IsType(base::MessageLoop::TYPE_IO));
}

void SetupDialog::PostUITask(const base::Closure& task) {
  ui_loop_->PostTask(FROM_HERE, task);
}

void SetupDialog::PostIOTask(const base::Closure& task) {
  io_loop_->PostTask(FROM_HERE, task);
}

void SetupDialog::ShowErrorMessageBox(const base::string16& error_message) {
  DCHECK(base::MessageLoopForUI::IsCurrent());
  MessageBox(error_message.c_str(),
             LoadLocalString(IDS_OPERATION_FAILED_TITLE).c_str(),
             MB_ICONERROR | MB_OK);
}

void SetupDialog::AskToCloseChrome() {
  DCHECK(base::MessageLoopForUI::IsCurrent());
  MessageBox(LoadLocalString(IDS_ADD_PRINTERS_USING_CHROME).c_str(),
             LoadLocalString(IDS_CONTINUE_IN_CHROME_TITLE).c_str(),
             MB_OK);
}

void SetupDialog::SetState(ServiceController::State status,
                           const base::string16& user,
                           bool is_logging_enabled) {
  DCHECK(base::MessageLoopForUI::IsCurrent());
  state_ = status;

  DWORD status_string = 0;
  switch(status) {
  case ServiceController::STATE_NOT_FOUND:
    status_string = IDS_SERVICE_NOT_FOUND;
    break;
  case ServiceController::STATE_STOPPED:
    status_string = IDS_SERVICE_STOPPED;
    break;
  case ServiceController::STATE_RUNNING:
    status_string = IDS_SERVICE_RUNNING;
    break;
  case ServiceController::STATE_UNKNOWN:
    break;
  }
  SetDlgItemText(IDC_STATUS,
                 status_string ? LoadLocalString(status_string).c_str() : L"");
  if (IsInstalled()) {
    SetDlgItemText(IDC_USER, user.c_str());
    CheckDlgButton(IDC_LOGGING,
                   is_logging_enabled ? BST_CHECKED : BST_UNCHECKED);
  }

  ATL::CWindow start_button = GetDlgItem(IDC_START);
  DWORD start_string = (status == ServiceController::STATE_STOPPED) ?
                       IDS_SERVICE_START : IDS_SERVICE_STOP;
  start_button.SetWindowText(LoadLocalString(start_string).c_str());
  start_button.ShowWindow(IsInstalled() ? SW_SHOW : SW_HIDE);
  start_button.EnableWindow(TRUE);

  ATL::CWindow install_button = GetDlgItem(IDC_INSTALL);
  DWORD install_string = IsInstalled() ? IDS_SERVICE_UNINSTALL :
                                         IDS_SERVICE_INSTALL;
  install_button.SetWindowText(LoadLocalString(install_string).c_str());
  install_button.ShowWindow(SW_SHOW);
  install_button.EnableWindow(TRUE);

  if (!IsInstalled()) {
    GetDlgItem(IDC_USER).EnableWindow(TRUE);
    GetDlgItem(IDC_PASSWORD).EnableWindow(TRUE);
    GetDlgItem(IDC_LOGGING).EnableWindow(TRUE);
  }
}

LRESULT SetupDialog::OnInitDialog(UINT message, WPARAM wparam, LPARAM lparam,
                                  BOOL& handled) {
  ATLVERIFY(CenterWindow());

  WTL::CIcon icon;
  if (icon.LoadIcon(MAKEINTRESOURCE(IDI_ICON))) {
    SetIcon(icon);
  }

  SetWindowText(LoadLocalString(IDS_SETUP_PROGRAM_NAME).c_str());
  SetDlgItemText(IDC_STATE_LABEL, LoadLocalString(IDS_STATE_LABEL).c_str());
  SetDlgItemText(IDC_USER_LABEL, LoadLocalString(IDS_USER_LABEL).c_str());
  SetDlgItemText(IDC_PASSWORD_LABEL,
                 LoadLocalString(IDS_PASSWORD_LABEL).c_str());
  SetDlgItemText(IDC_LOGGING, LoadLocalString(IDS_LOGGING_LABEL).c_str());
  SetDlgItemText(IDCANCEL, LoadLocalString(IDS_CLOSE).c_str());

  SetState(ServiceController::STATE_UNKNOWN, L"", false);
  DisableControls();

  SetDlgItemText(IDC_USER, GetCurrentUserName().c_str());

  PostIOTask(base::Bind(&SetupDialog::UpdateState, this));

  return 0;
}

LRESULT SetupDialog::OnCtrColor(UINT message, WPARAM wparam, LPARAM lparam,
                                BOOL& handled) {
  HWND window = reinterpret_cast<HWND>(lparam);
  if (GetDlgItem(IDC_LOGO).m_hWnd == window) {
    return reinterpret_cast<LRESULT>(::GetStockObject(WHITE_BRUSH));
  }
  return 0;
}

LRESULT SetupDialog::OnStart(UINT, INT nIdentifier, HWND, BOOL& handled) {
  DisableControls();
  DCHECK(IsInstalled());
  if (state_ == ServiceController::STATE_RUNNING)
    PostIOTask(base::Bind(&SetupDialog::Stop, this));
  else
    PostIOTask(base::Bind(&SetupDialog::Start, this));
  return 0;
}

LRESULT SetupDialog::OnInstall(UINT, INT nIdentifier, HWND, BOOL& handled) {
  DisableControls();
  if (IsInstalled()) {
    PostIOTask(base::Bind(&SetupDialog::Uninstall, this));
  } else {
    PostIOTask(base::Bind(&SetupDialog::Install, this, GetUser(),
                          GetPassword(), IsLoggingEnabled()));
  }
  return 0;
}

LRESULT SetupDialog::OnLogging(UINT, INT nIdentifier, HWND, BOOL& handled) {
  CheckDlgButton(IDC_LOGGING, IsLoggingEnabled()? BST_UNCHECKED : BST_CHECKED);
  return 0;
}

LRESULT SetupDialog::OnCancel(UINT, INT nIdentifier, HWND, BOOL& handled) {
  DestroyWindow();
  return 0;
}

LRESULT SetupDialog::OnDestroy(UINT message, WPARAM wparam, LPARAM lparam,
                               BOOL& handled) {
  base::MessageLoop::current()->PostTask(
      FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
  return 1;
}

void SetupDialog::DisableControls() {
  GetDlgItem(IDC_START).EnableWindow(FALSE);
  GetDlgItem(IDC_INSTALL).EnableWindow(FALSE);
  GetDlgItem(IDC_USER).EnableWindow(FALSE);
  GetDlgItem(IDC_PASSWORD).EnableWindow(FALSE);
  GetDlgItem(IDC_LOGGING).EnableWindow(FALSE);
}

base::string16 SetupDialog::GetDlgItemText(int id) const {
  const ATL::CWindow& item = GetDlgItem(id);
  size_t length = item.GetWindowTextLength();
  base::string16 result(length + 1, L'\0');
  result.resize(item.GetWindowText(&result[0],
                                   static_cast<int>(result.size())));
  return result;
}

base::string16 SetupDialog::GetUser() const {
  return GetDlgItemText(IDC_USER);
}

base::string16 SetupDialog::GetPassword() const {
  return GetDlgItemText(IDC_PASSWORD);
}

bool SetupDialog::IsLoggingEnabled() const{
  return IsDlgButtonChecked(IDC_LOGGING) == BST_CHECKED;
}

void SetupDialog::UpdateState() {
  DCHECK(base::MessageLoopForIO::IsCurrent());
  controller_.UpdateState();
  PostUITask(base::Bind(&SetupDialog::SetState, this, controller_.state(),
                        controller_.user(), controller_.is_logging_enabled()));
}

void SetupDialog::ShowError(const base::string16& error_message) {
  DCHECK(base::MessageLoopForIO::IsCurrent());
  PostUITask(base::Bind(&SetupDialog::SetState,
                        this,
                        ServiceController::STATE_UNKNOWN,
                        L"",
                        false));
  PostUITask(base::Bind(&SetupDialog::ShowErrorMessageBox, this,
                        error_message));
  LOG(ERROR) << error_message;
}

void SetupDialog::ShowError(int string_id) {
  ShowError(cloud_print::LoadLocalString(string_id));
}

void SetupDialog::ShowError(HRESULT hr) {
  ShowError(GetErrorMessage(hr));
}

void SetupDialog::Install(const base::string16& user,
                          const base::string16& password,
                          bool enable_logging) {
  // Don't forget to update state on exit.
  base::ScopedClosureRunner scoped_update_status(
        base::Bind(&SetupDialog::UpdateState, this));

  DCHECK(base::MessageLoopForIO::IsCurrent());

  SetupListener setup(GetUser());
  HRESULT hr = controller_.InstallCheckService(user, password,
                                               base::FilePath());
  if (FAILED(hr))
    return ShowError(hr);

  {
    // Always uninstall service after requirements check.
    base::ScopedClosureRunner scoped_uninstall(
        base::Bind(base::IgnoreResult(&ServiceController::UninstallService),
                   base::Unretained(&controller_)));

    hr = controller_.StartService();
    if (FAILED(hr))
      return ShowError(hr);

    if (!setup.WaitResponce(base::TimeDelta::FromSeconds(30)))
      return ShowError(IDS_ERROR_FAILED_START_SERVICE);
  }

  if (setup.user_data_dir().empty())
    return ShowError(IDS_ERROR_NO_DATA_DIR);

  if (setup.chrome_path().empty())
    return ShowError(IDS_ERROR_NO_CHROME);

  if (!setup.is_xps_available())
    return ShowError(IDS_ERROR_NO_XPS);

  base::FilePath file = setup.user_data_dir();
  file = file.Append(chrome::kServiceStateFileName);

  std::string proxy_id;
  std::string contents;

  if (base::ReadFileToString(file, &contents)) {
    ServiceState service_state;
    if (service_state.FromString(contents))
      proxy_id = service_state.proxy_id();
  }
  PostUITask(base::Bind(&SetupDialog::AskToCloseChrome, this));
  contents = ChromeLauncher::CreateServiceStateFile(proxy_id, setup.printers());

  if (contents.empty())
    return ShowError(IDS_ERROR_FAILED_CREATE_CONFIG);

  size_t written = base::WriteFile(file, contents.c_str(),
                                   static_cast<int>(contents.size()));
  if (written != contents.size()) {
    DWORD last_error = GetLastError();
    if (!last_error)
      return ShowError(IDS_ERROR_FAILED_CREATE_CONFIG);
    return ShowError(HRESULT_FROM_WIN32(last_error));
  }

  hr = controller_.InstallConnectorService(user, password, base::FilePath(),
                                           enable_logging);
  if (FAILED(hr))
    return ShowError(hr);

  hr = controller_.StartService();
  if (FAILED(hr))
    return ShowError(hr);
}

void SetupDialog::Start() {
  DCHECK(base::MessageLoopForIO::IsCurrent());
  HRESULT hr = controller_.StartService();
  if (FAILED(hr))
    ShowError(hr);
  UpdateState();
}

void SetupDialog::Stop() {
  DCHECK(base::MessageLoopForIO::IsCurrent());
  HRESULT hr = controller_.StopService();
  if (FAILED(hr))
    ShowError(hr);
  UpdateState();
}

void SetupDialog::Uninstall() {
  DCHECK(base::MessageLoopForIO::IsCurrent());
  HRESULT hr = controller_.UninstallService();
  if (FAILED(hr))
    ShowError(hr);
  UpdateState();
}

class CloudPrintServiceConfigModule
    : public ATL::CAtlExeModuleT<CloudPrintServiceConfigModule> {
};

CloudPrintServiceConfigModule _AtlModule;

int WINAPI WinMain(__in  HINSTANCE hInstance,
                   __in  HINSTANCE hPrevInstance,
                   __in  LPSTR lpCmdLine,
                   __in  int nCmdShow) {
  base::AtExitManager at_exit;
  base::CommandLine::Init(0, NULL);

  base::MessageLoopForUI loop;
  scoped_refptr<SetupDialog> dialog(new SetupDialog());
  dialog->Create(NULL);
  dialog->ShowWindow(SW_SHOW);
  SetupDialog::Dispatcher dispatcher(dialog.get());
  base::RunLoop run_loop(&dispatcher);
  run_loop.Run();
  return 0;
}
