// <copyright file="BasicMouseInterfaceTests.cs" company="Selenium Committers">
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
// </copyright>

using System.Drawing;
using OpenQA.Selenium.Interactions;

namespace OpenQA.Selenium.Tests.Interactions;

[TestFixture]
public class BasicMouseInterfaceTests : DriverTestFixture
{
    [SetUp]
    public void SetupTest()
    {
        if (Driver is IActionExecutor actionExecutor)
        {
            actionExecutor.ResetInputState();
        }
    }

    [Test]
    public void ShouldSetActivePointer()
    {
        Actions actionProvider = new Actions(Driver);
        actionProvider.SetActivePointer(PointerKind.Mouse, "test mouse");

        PointerInputDevice device = actionProvider.GetActivePointer();

        Assert.That(device.DeviceName, Is.EqualTo("test mouse"));
    }

    [Test]
    public void ShouldAllowDraggingElementWithMouseMovesItToAnotherList()
    {
        PerformDragAndDropWithMouse();
        IWebElement dragInto = Driver.FindElement(By.Id("sortable1"));
        Assert.That(dragInto.FindElements(By.TagName("li")), Has.Exactly(6).Items);
    }

    // This test is very similar to DraggingElementWithMouse. The only
    // difference is that this test also verifies the correct events were fired.
    [Test]
    public void DraggingElementWithMouseFiresEvents()
    {
        PerformDragAndDropWithMouse();
        IWebElement dragReporter = Driver.FindElement(By.Id("dragging_reports"));
        // This is failing under HtmlUnit. A bug was filed.
        Assert.That(dragReporter.Text, Does.Match("Nothing happened\\. (?:DragOut *)+DropIn RightItem 3"));
    }

    [Test]
    public void ShouldAllowDoubleClickThenNavigate()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement toDoubleClick = Driver.FindElement(By.Id("doubleClickField"));

        Actions actionProvider = new Actions(Driver);
        IAction dblClick = actionProvider.DoubleClick(toDoubleClick).Build();

        dblClick.Perform();
        Driver.Url = Urls.DroppableItems;
    }

    [Test]
    public void ShouldAllowDragAndDrop()
    {
        Driver.Url = Urls.DroppableItems;

        DateTime waitEndTime = DateTime.Now.Add(TimeSpan.FromSeconds(15));

        while (!IsElementAvailable(Driver, By.Id("draggable")) && (DateTime.Now < waitEndTime))
        {
            System.Threading.Thread.Sleep(200);
        }

        if (!IsElementAvailable(Driver, By.Id("draggable")))
        {
            throw new Exception("Could not find draggable element after 15 seconds.");
        }

        IWebElement toDrag = Driver.FindElement(By.Id("draggable"));
        IWebElement dropInto = Driver.FindElement(By.Id("droppable"));

        Actions actionProvider = new Actions(Driver);

        IAction holdDrag = actionProvider.ClickAndHold(toDrag).Build();

        IAction move = actionProvider.MoveToElement(dropInto).Build();

        IAction drop = actionProvider.Release(dropInto).Build();

        holdDrag.Perform();
        move.Perform();
        drop.Perform();

        dropInto = Driver.FindElement(By.Id("droppable"));
        string text = dropInto.FindElement(By.TagName("p")).Text;

        Assert.That(text, Is.EqualTo("Dropped!"));
    }

    [Test]
    public void ShouldAllowDoubleClick()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement toDoubleClick = Driver.FindElement(By.Id("doubleClickField"));

        Actions actionProvider = new Actions(Driver);
        IAction dblClick = actionProvider.DoubleClick(toDoubleClick).Build();

        dblClick.Perform();
        Assert.That(toDoubleClick.GetAttribute("value"), Is.EqualTo("DoubleClicked"));
    }

    [Test]
    public void ShouldAllowContextClick()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement toContextClick = Driver.FindElement(By.Id("doubleClickField"));

        Actions actionProvider = new Actions(Driver);
        IAction contextClick = actionProvider.ContextClick(toContextClick).Build();

        contextClick.Perform();
        Assert.That(toContextClick.GetAttribute("value"), Is.EqualTo("ContextClicked"));
    }

    [Test]
    [IgnoreBrowser(Browser.Remote, "API not implemented in driver")]
    public void ShouldAllowMoveAndClick()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement toClick = Driver.FindElement(By.Id("clickField"));

        Actions actionProvider = new Actions(Driver);
        IAction contextClick = actionProvider.MoveToElement(toClick).Click().Build();

        contextClick.Perform();
        Assert.That(toClick.GetAttribute("value"), Is.EqualTo("Clicked"), "Value should change to Clicked.");
    }

    [Test]
    [IgnoreBrowser(Browser.Remote, "API not implemented in driver")]
    public void ShouldAllowMoveAndClickDoubleWrappedElement()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement toClick = Driver.FindElement(By.Id("clickField"));

        toClick = new WebElementWrapper(toClick);
        toClick = new WebElementWrapper(toClick);

        Actions actionProvider = new Actions(Driver);
        IAction contextClick = actionProvider.MoveToElement(toClick).Click().Build();

        contextClick.Perform();
        Assert.That(toClick.GetAttribute("value"), Is.EqualTo("Clicked"), "Value should change to Clicked.");
    }

    [Test]
    [IgnoreBrowser(Browser.Chrome, "Not working properly in RBE, works locally with pinned browsers")]
    [IgnoreBrowser(Browser.Edge, "Not working properly in RBE, works locally with pinned browsers")]
    [IgnoreBrowser(Browser.Firefox, "Not working properly in RBE, works locally with pinned browsers")]
    public void ShouldMoveToLocation()
    {
        Driver.Url = Urls.MouseInteractionPage;

        Actions actionProvider = new Actions(Driver);
        actionProvider.MoveToLocation(100, 200).Build().Perform();

        IWebElement location = Driver.FindElement(By.Id("absolute-location"));
        var coordinates = location.Text.Split(',');
        Assert.That(coordinates[0].Trim(), Is.EqualTo("100"));
        Assert.That(coordinates[1].Trim(), Is.EqualTo("200"));
    }

    [Test]
    public void ShouldNotMoveToANullLocator()
    {
        Driver.Url = Urls.JavascriptPage;

        Assert.That(() => new Actions(Driver).MoveToElement(null).Perform(), Throws.InstanceOf<ArgumentException>());
    }

    [Test]
    [IgnoreBrowser(Browser.Chrome, "Drivers correctly click at current mouse position without another move, preserving mouse position.")]
    [IgnoreBrowser(Browser.Edge, "Drivers correctly click at current mouse position without another move, preserving mouse position.")]
    [IgnoreBrowser(Browser.Firefox, "Drivers correctly click at current mouse position without another move, preserving mouse position.")]
    [IgnoreBrowser(Browser.IE, "Drivers correctly click at current mouse position without another move, preserving mouse position.")]
    [IgnoreBrowser(Browser.Safari, "Drivers correctly click at current mouse position without another move, preserving mouse position.")]
    public void MousePositionIsNotPreservedInActionsChain()
    {
        Driver.Url = Urls.JavascriptPage;
        IWebElement toMoveTo = Driver.FindElement(By.Id("clickField"));

        new Actions(Driver).MoveToElement(toMoveTo).Perform();
        Assert.That(() => new Actions(Driver).Click().Perform(), Throws.InstanceOf<WebDriverException>());
    }

    [Test]
    [IgnoreBrowser(Browser.All, "Behaviour not finalized yet regarding linked images.")]
    public void MovingIntoAnImageEnclosedInALink()
    {
        Driver.Url = Urls.LinkedImage;

        // Note: For some reason, the Accessibility API in Firefox will not be available before we
        // click on something. As a work-around, click on a different element just to get going.
        Driver.FindElement(By.Id("linkToAnchorOnThisPage")).Click();

        IWebElement linkElement = Driver.FindElement(By.Id("linkWithEnclosedImage"));

        // Image is 644 x 41 - move towards the end.
        // Note: The width of the link element itself is correct - 644 pixels. However,
        // the height is 17 pixels and the rectangle containing it is *underneath* the image.
        // For this reason, this action will fail.
        new Actions(Driver).MoveToElement(linkElement, 500, 30).Click().Perform();

        WaitFor(TitleToBe("We Arrive Here"), "Title was not expected value");
    }

    [Test]
    [IgnoreBrowser(Browser.Chrome, "Moving outside of view port throws exception in spec-compliant driver")]
    [IgnoreBrowser(Browser.Edge, "Moving outside of view port throws exception in spec-compliant driver")]
    [IgnoreBrowser(Browser.Firefox, "Moving outside of view port throws exception in spec-compliant driver")]
    [IgnoreBrowser(Browser.IE, "Moving outside of view port throws exception in spec-compliant driver")]
    [IgnoreBrowser(Browser.Safari, "Moving outside of view port throws exception in spec-compliant driver")]
    public void MovingMouseBackAndForthPastViewPort()
    {
        Driver.Url = Urls.WhereIs("veryLargeCanvas.html");

        IWebElement firstTarget = Driver.FindElement(By.Id("r1"));
        new Actions(Driver).MoveToElement(firstTarget).Click().Perform();

        IWebElement resultArea = Driver.FindElement(By.Id("result"));
        String expectedEvents = "First";
        WaitFor(ElementTextToEqual(resultArea, expectedEvents), "Element text did not equal " + expectedEvents);

        // Move to element with id 'r2', at (2500, 50) to (2580, 100)
        new Actions(Driver).MoveByOffset(2540 - 150, 75 - 125).Click().Perform();
        expectedEvents += " Second";
        WaitFor(ElementTextToEqual(resultArea, expectedEvents), "Element text did not equal " + expectedEvents);

        // Move to element with id 'r3' at (60, 1500) to (140, 1550)
        new Actions(Driver).MoveByOffset(100 - 2540, 1525 - 75).Click().Perform();
        expectedEvents += " Third";
        WaitFor(ElementTextToEqual(resultArea, expectedEvents), "Element text did not equal " + expectedEvents);

        // Move to element with id 'r4' at (220,180) to (320, 230)
        new Actions(Driver).MoveByOffset(270 - 100, 205 - 1525).Click().Perform();
        expectedEvents += " Fourth";
        WaitFor(ElementTextToEqual(resultArea, expectedEvents), "Element text did not equal " + expectedEvents);
    }

    [Test]
    public void ShouldClickElementInIFrame()
    {
        Driver.Url = Urls.ClicksPage;
        try
        {
            Driver.SwitchTo().Frame("source");
            IWebElement element = Driver.FindElement(By.Id("otherframe"));
            new Actions(Driver).MoveToElement(element).Click().Perform();
            Driver.SwitchTo().DefaultContent().SwitchTo().Frame("target");
            WaitFor(() => { return Driver.FindElement(By.Id("span")).Text == "An inline element"; }, "Could not find element with text 'An inline element'");
        }
        finally
        {
            Driver.SwitchTo().DefaultContent();
        }
    }

    [Test]
    public void ShouldAllowUsersToHoverOverElements()
    {
        Driver.Url = Urls.JavascriptPage;

        IWebElement element = Driver.FindElement(By.Id("menu1"));

        IWebElement item = Driver.FindElement(By.Id("item1"));
        Assert.That(item.Text, Is.EqualTo(""));

        ((IJavaScriptExecutor)Driver).ExecuteScript("arguments[0].style.background = 'green'", element);
        Actions actionBuilder = new Actions(Driver);
        actionBuilder.MoveToElement(element).Perform();

        item = Driver.FindElement(By.Id("item1"));
        Assert.That(item.Text, Is.EqualTo("Item 1"));
    }

    [Test]
    public void HoverPersists()
    {
        Driver.Url = Urls.JavascriptPage;
        // Move to a different element to make sure the mouse is not over the
        // element with id 'item1' (from a previous test).
        new Actions(Driver).MoveToElement(Driver.FindElement(By.Id("dynamo"))).Perform();

        IWebElement element = Driver.FindElement(By.Id("menu1"));

        IWebElement item = Driver.FindElement(By.Id("item1"));
        Assert.That(item.Text, Is.Empty);

        ((IJavaScriptExecutor)Driver).ExecuteScript("arguments[0].style.background = 'green'", element);
        new Actions(Driver).MoveToElement(element).Perform();

        // Intentionally wait to make sure hover persists.
        System.Threading.Thread.Sleep(2000);

        WaitFor(ElementTextToNotEqual(item, ""), "Element text was empty after timeout");

        Assert.That(item.Text, Is.EqualTo("Item 1"));
    }

    [Test]
    public void MovingMouseByRelativeOffset()
    {
        Driver.Url = Urls.MouseTrackerPage;

        IWebElement trackerDiv = Driver.FindElement(By.Id("mousetracker"));
        new Actions(Driver).MoveToElement(trackerDiv).Build().Perform();

        IWebElement reporter = Driver.FindElement(By.Id("status"));

        WaitFor(FuzzyMatchingOfCoordinates(reporter, 50, 200), "Coordinate matching was not within tolerance");

        new Actions(Driver).MoveByOffset(10, 20).Build().Perform();

        WaitFor(FuzzyMatchingOfCoordinates(reporter, 60, 220), "Coordinate matching was not within tolerance");
    }

    [Test]
    public void MovingMouseToRelativeElementOffset()
    {
        Driver.Url = Urls.MouseTrackerPage;

        IWebElement trackerDiv = Driver.FindElement(By.Id("mousetracker"));
        Size size = trackerDiv.Size;

        new Actions(Driver).MoveToElement(trackerDiv, 95 - size.Width / 2, 195 - size.Height / 2).Build().Perform();

        IWebElement reporter = Driver.FindElement(By.Id("status"));

        WaitFor(FuzzyMatchingOfCoordinates(reporter, 95, 195), "Coordinate matching was not within tolerance");
    }

    [Test]
    public void MovingMouseToRelativeZeroElementOffset()
    {
        Driver.Url = Urls.MouseTrackerPage;

        IWebElement trackerDiv = Driver.FindElement(By.Id("mousetracker"));
        Size size = trackerDiv.Size;

        new Actions(Driver).MoveToElement(trackerDiv, -size.Width / 2, -size.Height / 2).Perform();

        IWebElement reporter = Driver.FindElement(By.Id("status"));

        WaitFor(FuzzyMatchingOfCoordinates(reporter, 0, 0), "Coordinate matching was not within tolerance");
    }

    [Test]
    [NeedsFreshDriver(IsCreatedBeforeTest = true)]
    public void MoveRelativeToBody()
    {
        Driver.Url = Urls.MouseTrackerPage;

        new Actions(Driver).MoveByOffset(50, 100).Build().Perform();

        IWebElement reporter = Driver.FindElement(By.Id("status"));

        WaitFor(FuzzyMatchingOfCoordinates(reporter, 50, 100), "Coordinate matching was not within tolerance");
    }

    [Test]
    public void MoveMouseByOffsetOverAndOutOfAnElement()
    {
        Driver.Url = Urls.MouseOverPage;

        IWebElement greenbox = Driver.FindElement(By.Id("greenbox"));
        IWebElement redbox = Driver.FindElement(By.Id("redbox"));
        Point greenboxPosition = greenbox.Location;
        Point redboxPosition = redbox.Location;
        int shiftX = redboxPosition.X - greenboxPosition.X;
        int shiftY = redboxPosition.Y - greenboxPosition.Y;

        Size greenBoxSize = greenbox.Size;
        int xOffset = 2 - greenBoxSize.Width / 2;
        int yOffset = 2 - greenBoxSize.Height / 2;

        new Actions(Driver).MoveToElement(greenbox, xOffset, yOffset).Perform();
        WaitFor(ElementColorToBe(redbox, Color.Green), "element color was not green");

        new Actions(Driver).MoveToElement(greenbox, xOffset, yOffset).MoveByOffset(shiftX, shiftY).Perform();
        WaitFor(ElementColorToBe(redbox, Color.Red), "element color was not red");

        new Actions(Driver).MoveToElement(greenbox, xOffset, yOffset).MoveByOffset(shiftX, shiftY).MoveByOffset(-shiftX, -shiftY).Perform();
        WaitFor(ElementColorToBe(redbox, Color.Green), "element color was not red");
    }

    [Test]
    public void CanMouseOverAndOutOfAnElement()
    {
        Driver.Url = Urls.MouseOverPage;

        IWebElement greenbox = Driver.FindElement(By.Id("greenbox"));
        IWebElement redbox = Driver.FindElement(By.Id("redbox"));
        Size greenSize = greenbox.Size;
        Size redSize = redbox.Size;

        new Actions(Driver).MoveToElement(greenbox, 1 - greenSize.Width / 2, 1 - greenSize.Height / 2).Perform();
        Assert.That(redbox.GetCssValue("background-color"), Is.EqualTo("rgba(0, 128, 0, 1)").Or.EqualTo("rgb(0, 128, 0)"));

        new Actions(Driver).MoveToElement(redbox).Perform();
        Assert.That(redbox.GetCssValue("background-color"), Is.EqualTo("rgba(255, 0, 0, 1)").Or.EqualTo("rgb(255, 0, 0)"));

        new Actions(Driver).MoveToElement(redbox, redSize.Width / 2 + 2, redSize.Height / 2 + 2).Perform();
        Assert.That(redbox.GetCssValue("background-color"), Is.EqualTo("rgba(0, 128, 0, 1)").Or.EqualTo("rgb(0, 128, 0)"));
    }

    private Func<bool> FuzzyMatchingOfCoordinates(IWebElement element, int x, int y)
    {
        return () =>
        {
            return FuzzyPositionMatching(x, y, element.Text);
        };
    }

    private bool FuzzyPositionMatching(int expectedX, int expectedY, String locationTuple)
    {
        string[] splitString = locationTuple.Split(',');
        int gotX = Convert.ToInt16(Math.Round(Convert.ToDouble(splitString[0].Trim())));
        int gotY = Convert.ToInt16(Math.Round(Convert.ToDouble(splitString[1].Trim())));

        // Everything within 5 pixels range is OK
        const int ALLOWED_DEVIATION = 5;
        return Math.Abs(expectedX - gotX) < ALLOWED_DEVIATION && Math.Abs(expectedY - gotY) < ALLOWED_DEVIATION;
    }

    private void PerformDragAndDropWithMouse()
    {
        Driver.Url = Urls.DraggableLists;

        IWebElement dragReporter = Driver.FindElement(By.Id("dragging_reports"));

        IWebElement toDrag = Driver.FindElement(By.Id("rightitem-3"));
        IWebElement dragInto = Driver.FindElement(By.Id("sortable1"));

        IAction holdItem = new Actions(Driver).ClickAndHold(toDrag).Build();

        IAction moveToSpecificItem = new Actions(Driver).MoveToElement(Driver.FindElement(By.Id("leftitem-4"))).Build();

        IAction moveToOtherList = new Actions(Driver).MoveToElement(dragInto).Build();

        IAction drop = new Actions(Driver).Release(dragInto).Build();

        Assert.That(dragReporter.Text, Is.EqualTo("Nothing happened."));

        holdItem.Perform();
        moveToSpecificItem.Perform();
        moveToOtherList.Perform();

        Assert.That(dragReporter.Text, Does.Match("Nothing happened\\. (?:DragOut *)+"));
        drop.Perform();
    }

    private bool IsElementAvailable(IWebDriver driver, By locator)
    {
        try
        {
            driver.FindElement(locator);
            return true;
        }
        catch (NoSuchElementException)
        {
            return false;
        }
    }

    private Func<bool> TitleToBe(string desiredTitle)
    {
        return () => Driver.Title == desiredTitle;
    }

    private Func<bool> ValueToBe(IWebElement element, string desiredValue)
    {
        return () => element.GetDomProperty("value") == desiredValue;
    }

    private Func<bool> ElementTextToEqual(IWebElement element, string text)
    {
        return () => element.Text == text;
    }

    private Func<bool> ElementTextToNotEqual(IWebElement element, string text)
    {
        return () => element.Text != text;
    }

    private Func<bool> ElementColorToBe(IWebElement element, Color color)
    {
        return () =>
        {
            string rgb = string.Format("rgb({0}, {1}, {2})", color.R, color.G, color.B);
            string rgba = string.Format("rgba({0}, {1}, {2}, 1)", color.R, color.G, color.B);
            string value = element.GetCssValue("background-color");
            return value == rgb || value == rgba;
        };
    }
}
