/*
 * Copyright (C) 2011, 2015 Apple Inc. All rights reserved.
 * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#ifndef PopupMenuWin_h
#define PopupMenuWin_h

#include "COMPtr.h"
#include "IntRect.h"
#include "PopupMenu.h"
#include "PopupMenuClient.h"
#include "ScrollableArea.h"
#include "Scrollbar.h"
#include <OleAcc.h>
#include <wtf/RefPtr.h>
#include <wtf/win/GDIObject.h>

namespace WebCore {

class FrameView;
class Scrollbar;
class AccessiblePopupMenu;

class PopupMenuWin : public PopupMenu, private ScrollableArea {
public:
    PopupMenuWin(PopupMenuClient*);
    ~PopupMenuWin();

    void show(const IntRect&, FrameView*, int index) override;
    void hide() override;
    void updateFromElement() override;
    void disconnectClient() override;

    static LPCWSTR popupClassName();

    String debugDescription() const final;

private:
    PopupMenuClient* client() const { return m_popupClient; }

    Scrollbar* scrollbar() const { return m_scrollbar.get(); }

    bool up(unsigned lines = 1);
    bool down(unsigned lines = 1);

    int itemHeight() const { return m_itemHeight; }
    const IntRect& windowRect() const { return m_windowRect; }
    IntRect clientRect() const;

    int visibleItems() const;

    int listIndexAtPoint(const IntPoint&) const;

    bool setFocusedIndex(int index, bool hotTracking = false);
    int focusedIndex() const;
    void focusFirst();
    void focusLast();

    void paint(const IntRect& damageRect, HDC = 0);

    HWND popupHandle() const { return m_popup; }

    void setWasClicked(bool b = true) { m_wasClicked = b; }
    bool wasClicked() const { return m_wasClicked; }

    bool scrollToRevealSelection();

    void incrementWheelDelta(int delta);
    void reduceWheelDelta(int delta);
    int wheelDelta() const { return m_wheelDelta; }

    bool scrollbarCapturingMouse() const { return m_scrollbarCapturingMouse; }
    void setScrollbarCapturingMouse(bool b) { m_scrollbarCapturingMouse = b; }

    // ScrollableArea
    ScrollPosition scrollPosition() const override;
    void setScrollOffset(const IntPoint&) override;
    void invalidateScrollbarRect(Scrollbar&, const IntRect&) override;
    void invalidateScrollCornerRect(const IntRect&) override { }
    bool isActive() const override { return true; }
    ScrollableArea* enclosingScrollableArea() const override { return 0; }
    bool isScrollableOrRubberbandable() override { return true; }
    bool hasScrollableOrRubberbandableAncestor() override { return true; }
    bool isScrollCornerVisible() const override { return false; }
    IntRect scrollCornerRect() const override { return IntRect(); }
    Scrollbar* verticalScrollbar() const override { return m_scrollbar.get(); }
    IntSize visibleSize() const override;
    IntSize contentsSize() const override;
    IntRect scrollableAreaBoundingBox(bool* = nullptr) const override;
    bool forceUpdateScrollbarsOnMainThreadForPerformanceTesting() const override { return false; }
    bool shouldPlaceVerticalScrollbarOnLeft() const final { return false; }

    // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
    void scrollTo(int offset);

    void calculatePositionAndSize(const IntRect&, FrameView*);
    void invalidateItem(int index);

    bool onGetObject(WPARAM wParam, LPARAM lParam, LRESULT& lResult);

    static LRESULT CALLBACK PopupMenuWndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
    static void registerClass();

    RefPtr<Scrollbar> m_scrollbar;
    COMPtr<IAccessible> m_accessiblePopupMenu;
    GDIObject<HDC> m_DC;
    GDIObject<HBITMAP> m_bmp;
    PopupMenuClient* m_popupClient;
    HWND m_popup { nullptr };
    IntRect m_windowRect;
    int m_itemHeight { 0 };
    int m_scrollOffset { 0 };
    int m_wheelDelta { 0 };
    int m_focusedIndex { 0 };
    int m_hoveredIndex { 0 };
    bool m_wasClicked { false };
    bool m_scrollbarCapturingMouse { false };
    bool m_showPopup { false };
    float m_scaleFactor { 1 };
    FontCascade m_font;

    friend class AccessiblePopupMenu;
};

class AccessiblePopupMenu final : public IAccessible {
public:
    AccessiblePopupMenu(const PopupMenuWin&);
    ~AccessiblePopupMenu();

    // IUnknown
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(_In_ REFIID, _COM_Outptr_ void**);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    // IDispatch - Not to be implemented.
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(_Out_ UINT* count);
    virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT, LCID, _COM_Outptr_opt_ ITypeInfo**);
    virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(_In_ REFIID, __in_ecount(cNames) LPOLESTR*, UINT cNames, LCID, __out_ecount_full(cNames) DISPID*);
    virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID, REFIID, LCID, WORD, DISPPARAMS*, VARIANT*, EXCEPINFO*, UINT*);

    // IAccessible
    virtual HRESULT STDMETHODCALLTYPE get_accParent(_COM_Outptr_opt_ IDispatch**);
    virtual HRESULT STDMETHODCALLTYPE get_accChildCount(_Out_ long*);
    virtual HRESULT STDMETHODCALLTYPE get_accChild(VARIANT vChild, _COM_Outptr_opt_ IDispatch** ppChild);
    virtual HRESULT STDMETHODCALLTYPE get_accName(VARIANT vChild, __deref_out_opt BSTR*);
    virtual HRESULT STDMETHODCALLTYPE get_accValue(VARIANT vChild, __deref_out_opt BSTR*);
    virtual HRESULT STDMETHODCALLTYPE get_accDescription(VARIANT, __deref_out_opt BSTR*);
    virtual HRESULT STDMETHODCALLTYPE get_accRole(VARIANT vChild, _Out_ VARIANT* pvRole);
    virtual HRESULT STDMETHODCALLTYPE get_accState(VARIANT vChild, _Out_ VARIANT* pvState);
    virtual HRESULT STDMETHODCALLTYPE get_accHelp(VARIANT vChild, __deref_out_opt BSTR* helpText);
    virtual HRESULT STDMETHODCALLTYPE get_accKeyboardShortcut(VARIANT vChild, __deref_out_opt BSTR*);
    virtual HRESULT STDMETHODCALLTYPE get_accFocus(_Out_ VARIANT* pvFocusedChild);
    virtual HRESULT STDMETHODCALLTYPE get_accSelection(_Out_ VARIANT* pvSelectedChild);
    virtual HRESULT STDMETHODCALLTYPE get_accDefaultAction(VARIANT vChild, __deref_out_opt BSTR* actionDescription);
    virtual HRESULT STDMETHODCALLTYPE accSelect(long selectionFlags, VARIANT vChild);
    virtual HRESULT STDMETHODCALLTYPE accLocation(_Out_ long* left, _Out_ long* top, _Out_ long* width, _Out_ long* height, VARIANT vChild);
    virtual HRESULT STDMETHODCALLTYPE accNavigate(long direction, VARIANT vFromChild, _Out_ VARIANT* pvNavigatedTo);
    virtual HRESULT STDMETHODCALLTYPE accHitTest(long x, long y, _Out_ VARIANT* pvChildAtPoint);
    virtual HRESULT STDMETHODCALLTYPE accDoDefaultAction(VARIANT vChild);
    virtual HRESULT STDMETHODCALLTYPE put_accName(VARIANT, _In_ BSTR);
    virtual HRESULT STDMETHODCALLTYPE put_accValue(VARIANT, _In_ BSTR);
    virtual HRESULT STDMETHODCALLTYPE get_accHelpTopic(BSTR* helpFile, VARIANT, _Out_ long* topicID);

private:
    int m_refCount { 0 };
    const PopupMenuWin& m_popupMenu;
};

} // namespace WebCore

#endif // PopupMenuWin_h
