/* Copyright 2015 the SumatraPDF project authors (see AUTHORS file).
   License: Simplified BSD (see COPYING.BSD) */

class HwndWrapper;
class Control;

class ControlEvents {
  public:
    std::function<void(Control *, int, int)> Clicked;
    std::function<void(Control *, int, int)> SizeChanged;
};

class NamedEvents {
  public:
    std::function<void(Control *, int, int)> Clicked;
};

// A single EventMgr is associated with a single HwndWrapper
// (which itself is associated with single HWND) and handles
// win32 messages for that HWND needed to make the whole system
// work.
class EventMgr {
    HwndWrapper *wndRoot;
    // current window over which the mouse is
    Control *currOver;

    Size minSize;
    Size maxSize;

    bool inSizeMove;

    struct EventHandler {
        Control *ctrlSource;
        ControlEvents *events;
    };
    Vec<EventHandler> eventHandlers;

    struct NamedEventHandler {
        const char *name;
        NamedEvents *namedEvents;
    };
    Vec<NamedEventHandler> namedEventHandlers;

    LRESULT OnSetCursor(int x, int y, bool &wasHandled);
    LRESULT OnMouseMove(WPARAM keys, int x, int y, bool &wasHandled);
    LRESULT OnLButtonUp(WPARAM keys, int x, int y, bool &wasHandled);
    LRESULT OnGetMinMaxInfo(MINMAXINFO *info, bool &wasHandled);

  public:
    EventMgr(HwndWrapper *wndRoot);
    ~EventMgr();

    LRESULT OnMessage(UINT msg, WPARAM wParam, LPARAM lParam, bool &handledOut);

    ControlEvents *EventsForControl(Control *c);
    NamedEvents *EventsForName(const char *name);

    void RemoveEventsForControl(Control *c);

    void NotifyClicked(Control *c, int x, int y);
    void NotifySizeChanged(Control *c, int dx, int dy);
    void NotifyNamedEventClicked(Control *c, int x, int y);

    bool IsInSizeMove() const { return inSizeMove; }

    void SetMinSize(Size s);
    void SetMaxSize(Size s);
};