/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"

#include <gtest/gtest.h>

#include "Color.h"
#include "KeyboardCodes.h"
#include "PopupMenu.h"
#include "PopupMenuClient.h"
#include "PopupMenuChromium.h"
#include "WebFrameClient.h"
#include "WebFrameImpl.h"
#include "WebInputEvent.h"
#include "WebPopupMenuImpl.h"
#include "WebScreenInfo.h"
#include "WebViewClient.h"
#include "WebViewImpl.h"

using namespace WebCore;
using namespace WebKit;

namespace {

class TestPopupMenuClient : public PopupMenuClient {
public:
    // Item at index 0 is selected by default.
    TestPopupMenuClient() : m_selectIndex(0) { }
    virtual ~TestPopupMenuClient() {}
    virtual void valueChanged(unsigned listIndex, bool fireEvents = true)
    {
        m_selectIndex = listIndex;
    }
    virtual void selectionChanged(unsigned, bool) {}
    virtual void selectionCleared() {}

    virtual String itemText(unsigned listIndex) const
    {
        String str("Item ");
        str.append(String::number(listIndex));
        return str;
    }
    virtual String itemLabel(unsigned) const { return String(); }
    virtual String itemIcon(unsigned) const { return String(); }
    virtual String itemToolTip(unsigned listIndex) const { return itemText(listIndex); }
    virtual String itemAccessibilityText(unsigned listIndex) const { return itemText(listIndex); }
    virtual bool itemIsEnabled(unsigned listIndex) const { return true; }
    virtual PopupMenuStyle itemStyle(unsigned listIndex) const
    {
        Font font(FontPlatformData(12.0, false, false), false);
        return PopupMenuStyle(Color::black, Color::white, font, true, false, Length(), TextDirection(), false /* has text direction override */);
    }
    virtual PopupMenuStyle menuStyle() const { return itemStyle(0); }
    virtual int clientInsetLeft() const { return 0; }
    virtual int clientInsetRight() const { return 0; }
    virtual int clientPaddingLeft() const { return 0; }
    virtual int clientPaddingRight() const { return 0; }
    virtual int listSize() const { return 10; }
    virtual int selectedIndex() const { return m_selectIndex; }
    virtual void popupDidHide() { }
    virtual bool itemIsSeparator(unsigned listIndex) const { return false; }
    virtual bool itemIsLabel(unsigned listIndex) const { return false; }
    virtual bool itemIsSelected(unsigned listIndex) const { return listIndex == m_selectIndex; }
    virtual bool shouldPopOver() const { return false; }
    virtual bool valueShouldChangeOnHotTrack() const { return false; }
    virtual void setTextFromItem(unsigned listIndex) { }
    
    virtual FontSelector* fontSelector() const { return 0; }
    virtual HostWindow* hostWindow() const { return 0; }
    
    virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) { return 0; }

private:
    unsigned m_selectIndex;
};

class TestWebWidgetClient : public WebWidgetClient {
public:
    ~TestWebWidgetClient() { }
};

class TestWebPopupMenuImpl : public WebPopupMenuImpl {
public:
    static PassRefPtr<TestWebPopupMenuImpl> create(WebWidgetClient* client)
    {
        return adoptRef(new TestWebPopupMenuImpl(client));
    }

    ~TestWebPopupMenuImpl() { }

private:
    TestWebPopupMenuImpl(WebWidgetClient* client) : WebPopupMenuImpl(client) { }
};

class TestWebWidget : public WebWidget {
public:
    virtual ~TestWebWidget() { }
    virtual void close() { }
    virtual WebSize size() { return WebSize(100, 100); }
    virtual void resize(const WebSize&) { }
    virtual void layout() { }
    virtual void paint(WebCanvas*, const WebRect&) { }
    virtual void themeChanged() { }
    virtual void composite(bool finish) { }
    virtual bool handleInputEvent(const WebInputEvent&) { return true; }
    virtual void mouseCaptureLost() { }
    virtual void setFocus(bool) { }
    virtual bool setComposition(
        const WebString& text,
        const WebVector<WebCompositionUnderline>& underlines,
        int selectionStart,
        int selectionEnd) { return true; }
    virtual bool confirmComposition() { return true; }
    virtual bool confirmComposition(const WebString& text) { return true; }
    virtual WebTextInputType textInputType() { return WebKit::WebTextInputTypeNone; }
    virtual WebRect caretOrSelectionBounds() { return WebRect(); }
    virtual bool selectionRange(WebPoint& start, WebPoint& end) const { return false; }
    virtual void setTextDirection(WebTextDirection) { }
};

class TestWebViewClient : public WebViewClient {
public:
    TestWebViewClient() : m_webPopupMenu(TestWebPopupMenuImpl::create(&m_webWidgetClient)) { }
    ~TestWebViewClient() { }

    virtual WebWidget* createPopupMenu(WebPopupType) { return m_webPopupMenu.get(); }

    // We need to override this so that the popup menu size is not 0
    // (the layout code checks to see if the popup fits on the screen).
    virtual WebScreenInfo screenInfo()
    { 
        WebScreenInfo screenInfo;
        screenInfo.availableRect.height = 2000;
        screenInfo.availableRect.width = 2000;
        return screenInfo;
    }

private:
    TestWebWidgetClient m_webWidgetClient;
    RefPtr<TestWebPopupMenuImpl> m_webPopupMenu;
};

class TestWebFrameClient : public WebFrameClient {
public:
    ~TestWebFrameClient() { }
};

class SelectPopupMenuTest : public testing::Test {
public:
    SelectPopupMenuTest()
    {
    }

protected:
    virtual void SetUp()
    {
        m_webView = static_cast<WebViewImpl*>(WebView::create(&m_webviewClient));
        m_webView->initializeMainFrame(&m_webFrameClient);
        m_popupMenu = adoptRef(new PopupMenuChromium(&m_popupMenuClient));
    }

    virtual void TearDown()
    {
        m_popupMenu = 0;
        m_webView->close();
    }

    // Returns true if there currently is a select popup in the WebView.
    bool popupOpen() const { return m_webView->selectPopup(); }

    int selectedIndex() const { return m_popupMenuClient.selectedIndex(); }

    void showPopup()
    {
        m_popupMenu->show(IntRect(0, 0, 100, 100),
            static_cast<WebFrameImpl*>(m_webView->mainFrame())->frameView(), 0);
        ASSERT_TRUE(popupOpen());
        EXPECT_TRUE(m_webView->selectPopup()->popupType() == PopupContainer::Select);
    }

    void hidePopup()
    {
        m_popupMenu->hide();
        EXPECT_FALSE(popupOpen());
    }

    void simulateKeyDownEvent(int keyCode)
    {
        simulateKeyEvent(WebInputEvent::RawKeyDown, keyCode);
    }

    void simulateKeyUpEvent(int keyCode)
    {
        simulateKeyEvent(WebInputEvent::KeyUp, keyCode);
    }

    // Simulates a key event on the WebView.
    // The WebView forwards the event to the select popup if one is open.
    void simulateKeyEvent(WebInputEvent::Type eventType, int keyCode)
    {
        WebKeyboardEvent keyEvent;
        keyEvent.windowsKeyCode = keyCode;
        keyEvent.type = eventType;
        m_webView->handleInputEvent(keyEvent);
    }

    // Simulates a mouse event on the select popup.
    void simulateLeftMouseDownEvent(const IntPoint& point)
    {
        PlatformMouseEvent mouseEvent(point, point, LeftButton, MouseEventPressed,
                                      1, false, false, false, false, 0);
        m_webView->selectPopup()->handleMouseDownEvent(mouseEvent);
    }
    void simulateLeftMouseUpEvent(const IntPoint& point)
    {
        PlatformMouseEvent mouseEvent(point, point, LeftButton, MouseEventReleased,
                                      1, false, false, false, false, 0);
        m_webView->selectPopup()->handleMouseReleaseEvent(mouseEvent);
    }

protected:
    TestWebViewClient m_webviewClient;
    WebViewImpl* m_webView;
    TestWebFrameClient m_webFrameClient;
    TestPopupMenuClient m_popupMenuClient;
    RefPtr<PopupMenu> m_popupMenu;
};

// Tests that show/hide and repeats.  Select popups are reused in web pages when
// they are reopened, that what this is testing.
TEST_F(SelectPopupMenuTest, ShowThenHide)
{
    for (int i = 0; i < 3; i++) {
        showPopup();
        hidePopup();
    }
}

// Tests that showing a select popup and deleting it does not cause problem.
// This happens in real-life if a page navigates while a select popup is showing.
TEST_F(SelectPopupMenuTest, ShowThenDelete)
{
    showPopup();
    // Nothing else to do, TearDown() deletes the popup.
}

// Tests that losing focus closes the select popup.
TEST_F(SelectPopupMenuTest, ShowThenLoseFocus)
{
    showPopup();
    // Simulate losing focus.
    m_webView->setFocus(false);

    // Popup should have closed.
    EXPECT_FALSE(popupOpen());
}

// Tests that pressing ESC closes the popup.
TEST_F(SelectPopupMenuTest, ShowThenPressESC)
{
    showPopup();
    simulateKeyDownEvent(VKEY_ESCAPE);
    // Popup should have closed.
    EXPECT_FALSE(popupOpen());
}

// Tests selecting an item with the arrows and enter/esc/tab.
TEST_F(SelectPopupMenuTest, SelectWithKeys)
{
    showPopup();
    // Simulate selecting the 2nd item by pressing Down, Down, enter.
    simulateKeyDownEvent(VKEY_DOWN);
    simulateKeyDownEvent(VKEY_DOWN);
    simulateKeyDownEvent(VKEY_RETURN);

    // Popup should have closed.
    EXPECT_TRUE(!popupOpen());
    EXPECT_EQ(2, selectedIndex());

    // It should work as well with ESC.
    showPopup();
    simulateKeyDownEvent(VKEY_DOWN);
    simulateKeyDownEvent(VKEY_ESCAPE);
    EXPECT_FALSE(popupOpen());
    EXPECT_EQ(3, selectedIndex());

    // It should work as well with TAB.
    showPopup();
    simulateKeyDownEvent(VKEY_DOWN);
    simulateKeyDownEvent(VKEY_TAB);
    EXPECT_FALSE(popupOpen());
    EXPECT_EQ(4, selectedIndex());
}

// Tests that selecting an item with the mouse does select the item and close
// the popup.
TEST_F(SelectPopupMenuTest, ClickItem)
{
    showPopup();

    // Y of 18 to be on the item at index 1 (12 font plus border and more to be safe).
    IntPoint row1Point(2, 18);
    // Simulate a click down/up on the first item.
    simulateLeftMouseDownEvent(row1Point);
    simulateLeftMouseUpEvent(row1Point);

    // Popup should have closed and the item at index 1 selected.
    EXPECT_FALSE(popupOpen());
    EXPECT_EQ(1, selectedIndex());
}

// Tests that moving the mouse over an item and then clicking outside the select popup
// leaves the seleted item unchanged.
TEST_F(SelectPopupMenuTest, MouseOverItemClickOutside)
{
    showPopup();

    // Y of 18 to be on the item at index 1 (12 font plus border and more to be safe).
    IntPoint row1Point(2, 18);
    // Simulate the mouse moving over the first item.
    PlatformMouseEvent mouseEvent(row1Point, row1Point, NoButton, MouseEventMoved,
                                  1, false, false, false, false, 0);
    m_webView->selectPopup()->handleMouseMoveEvent(mouseEvent);

    // Click outside the popup.
    simulateLeftMouseDownEvent(IntPoint(1000, 1000));

    // Popup should have closed and item 0 should still be selected.
    EXPECT_FALSE(popupOpen());
    EXPECT_EQ(0, selectedIndex());
}

// Tests that selecting an item with the keyboard and then clicking outside the select
// popup does select that item.
TEST_F(SelectPopupMenuTest, SelectItemWithKeyboardItemClickOutside)
{
    showPopup();

    // Simulate selecting the 2nd item by pressing Down, Down.
    simulateKeyDownEvent(VKEY_DOWN);
    simulateKeyDownEvent(VKEY_DOWN);

    // Click outside the popup.
    simulateLeftMouseDownEvent(IntPoint(1000, 1000));

    // Popup should have closed and the item should have been selected.
    EXPECT_FALSE(popupOpen());
    EXPECT_EQ(2, selectedIndex());
}

} // namespace
