// Copyright 2026 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_UPDATER_WIN_UI_WINDOW_IMPL_H_
#define CHROME_UPDATER_WIN_UI_WINDOW_IMPL_H_

#include <windows.h>

#include "base/memory/weak_ptr.h"
#include "ui/gfx/win/msg_util.h"
#include "ui/gfx/win/window_impl.h"

namespace updater::ui {

// Centers `hwnd` on `parent` (or on the work area of the monitor containing
// `hwnd` if `parent` is null).
void CenterWindow(HWND hwnd, HWND parent);

// Sends `msg` to every descendant of `hwnd`.
void SendMessageToDescendants(HWND hwnd,
                              UINT msg,
                              WPARAM wparam,
                              LPARAM lparam);

// Moves focus inside the dialog `dlg` to control `ctrl`.
void GotoDlgCtrl(HWND dlg, HWND ctrl);

// Dialog template-backed window. Used in place of ATL's `CDialogImpl<>`.
// Subclasses must provide an integer `IDD` member (the dialog resource ID)
// and a `ProcessWindowMessage(...)` method (typically generated by the
// `CR_BEGIN_MSG_MAP_EX` macro in `ui/gfx/win/msg_util.h`).
class DialogImpl : public gfx::MessageMapInterface {
 public:
  DialogImpl();
  DialogImpl(const DialogImpl&) = delete;
  DialogImpl& operator=(const DialogImpl&) = delete;
  ~DialogImpl() override;

  HWND hwnd() const { return hwnd_; }
  BOOL IsWindow() const { return hwnd_ && ::IsWindow(hwnd_); }

  // Creates the dialog from the resource template identified by `dialog_id`.
  // Returns the HWND on success, or nullptr.
  HWND Create(int dialog_id, HWND parent);

  // Destroys the dialog window if it is alive. Returns the result of the
  // underlying `::DestroyWindow` call.
  BOOL DestroyWindow();

 private:
  static INT_PTR CALLBACK DialogProc(HWND hwnd,
                                     UINT msg,
                                     WPARAM wparam,
                                     LPARAM lparam);

  HWND hwnd_ = nullptr;
};

// Helper for subclassing an existing HWND (typically a built-in Win32 control
// such as the system progress bar). Messages flow through this subclass
// instance's `ProcessWindowMessage` first; default handling chains to the
// original window procedure via `::DefSubclassProc`.
class SubclassedWindow : public gfx::MessageMapInterface {
 public:
  SubclassedWindow();
  SubclassedWindow(const SubclassedWindow&) = delete;
  SubclassedWindow& operator=(const SubclassedWindow&) = delete;
  ~SubclassedWindow() override;

  HWND hwnd() const { return hwnd_; }
  BOOL IsWindow() const { return hwnd_ && ::IsWindow(hwnd_); }

  // Subclasses `hwnd`. Returns whether the subclass was installed.
  BOOL SubclassWindow(HWND hwnd);

 private:
  static LRESULT CALLBACK SubclassProc(HWND hwnd,
                                       UINT msg,
                                       WPARAM wparam,
                                       LPARAM lparam,
                                       UINT_PTR id,
                                       DWORD_PTR ref_data);

  HWND hwnd_ = nullptr;
};

}  // namespace updater::ui

// Updater-local message-map macros that complement those in
// `ui/gfx/win/msg_util.h`.

// Walks into a base/mixin class's message map. Short-circuits on handled.
// `BaseClass` must define `BOOL ProcessWindowMessage(HWND, UINT, WPARAM,
// LPARAM, LRESULT&, DWORD)` (which `CR_BEGIN_MSG_MAP_EX` generates, but
// hand-written message-handling mixins can provide too).
#define CR_CHAIN_MSG_MAP(BaseClass)                                 \
  {                                                                 \
    LRESULT cr_chain_result_ = 0;                                   \
    if (BaseClass::ProcessWindowMessage(hWnd, uMsg, wParam, lParam, \
                                        cr_chain_result_, 0)) {     \
      lResult = cr_chain_result_;                                   \
      SetMsgHandled(TRUE);                                          \
      return TRUE;                                                  \
    }                                                               \
  }

#endif  // CHROME_UPDATER_WIN_UI_WINDOW_IMPL_H_
