/*
 * Copyright 2008-2011 Opera Software ASA
 *
 * Licensed 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.
 */

package com.opera.core.systems;

import com.opera.core.systems.scope.internal.OperaMouseKeys;
import org.openqa.selenium.Mouse;
import org.openqa.selenium.Point;
import org.openqa.selenium.interactions.InvalidCoordinatesException;
import org.openqa.selenium.interactions.internal.Coordinates;

public class OperaMouse implements Mouse {
  private final OperaDriver parent;

  public OperaMouse(OperaDriver parent) {
    this.parent = parent;
  }

  public void click(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to click on.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y, OperaMouseKeys.LEFT);
  }

  public void contextClick(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to context click on.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y, OperaMouseKeys.RIGHT);
  }

  public void doubleClick(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to double click on.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y, OperaMouseKeys.LEFT.getValue(), 2);
  }

  public void mouseDown(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to mouse down on.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y, OperaMouseKeys.LEFT_DOWN);
  }

  public void mouseUp(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to mouse up on.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y, OperaMouseKeys.LEFT_DOWN);
  }

  public void mouseMove(Coordinates where) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to mouse move to.");
    }
    Point p = where.getLocationInViewPort();
    parent.exec.mouseAction(p.x, p.y);
  }

  public void mouseMove(Coordinates where, long xOffset, long yOffset) {
    if (where == null) {
      throw new InvalidCoordinatesException("Invalid coordinates to mouse move to.");
    }

    Point p = where.getLocationInViewPort();

    /*
     * We can't compare against Integer.MAX_VALUE and throw, because this
     * method isn't defined as able to throw an Exception. Weird things will
     * just happen here...
     */
    int xO = (int) xOffset;
    int yO = (int) yOffset;
    parent.exec.mouseAction(p.x + xO, p.y + yO);
  }

}
@@ -973,16 +973,51 @@
  parent;
+%0A  private Point lastMousePosition;
 %0A%0A  publ
@@ -1132,158 +1132,41 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to click on.%22);%0A    %7D%0A    Point p = where.getLocationInViewPort(
+Point p = getPoint(where, %22click%22
 );%0A 
@@ -1285,97 +1285,35 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to 
+Point p = getPoint(where, %22
 cont
@@ -1325,67 +1325,12 @@
 lick
- on.
 %22);%0A
-    %7D%0A    Point p = where.getLocationInViewPort();%0A
     
@@ -1446,165 +1446,48 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to double click on.%22);%0A    %7D%0A    Point p = where.getLocationInViewPort(
+Point p = getPoint(where, %22double click%22
 );%0A 
@@ -1617,97 +1617,35 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to 
+Point p = getPoint(where, %22
 mous
@@ -1654,67 +1654,12 @@
 down
- on.
 %22);%0A
-    %7D%0A    Point p = where.getLocationInViewPort();%0A
     
@@ -1775,161 +1775,44 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to mouse up on.%22);%0A    %7D%0A    Point p = where.getLocationInViewPort(
+Point p = getPoint(where, %22mouse up%22
 );%0A 
@@ -1933,97 +1933,35 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to 
+Point p = getPoint(where, %22
 mous
@@ -1970,67 +1970,12 @@
 move
- to.
 %22);%0A
-    %7D%0A    Point p = where.getLocationInViewPort();%0A
     
@@ -2095,181 +2095,56 @@
     
-if (where == null) %7B%0A      throw new InvalidCoordinatesException(%22Invalid coordinates to mouse move to.%22);%0A    %7D%0A%0A    Point p = where.getLocationInViewPort();%0A%0A    /*%0A     *
+Point p = getPoint(where, %22mouse move%22);%0A%0A    //
  We 
@@ -2211,18 +2211,18 @@
 his%0A    
- *
+//
  method 
@@ -2288,18 +2288,18 @@
 ill%0A    
- *
+//
  just ha
@@ -2315,16 +2315,8 @@
 ...%0A
-     */%0A
     
@@ -2371,59 +2371,516 @@
 et;%0A
-    parent.exec.mouseAction(p.x + xO, p.y + yO);%0A  %7D%0A
+%0A    lastMousePosition = new Point(p.x + xO, p.y+yO);%0A    parent.exec.mouseAction(p.x + xO, p.y + yO);%0A  %7D%0A%0A  private Point getPoint(Coordinates where, String action) %7B%0A    // If coordinates exist then we want to update the last known mouse%0A    // position and then use it in the action.%0A    if (where != null) lastMousePosition = where.getLocationInViewPort();%0A    if (lastMousePosition != null) return lastMousePosition;%0A%0A    throw new InvalidCoordinatesException(%22Invalid coordinates to %22+action+%22 on%22);%0A  %7D
 %0A%7D

Update OperaMouse to store last mouse position