// Copyright 2017 Google Inc. All Rights Reserved.
//
// 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.

import 'package:webdriver/src/common/mouse.dart';
import 'package:webdriver/src/common/request_client.dart';
import 'package:webdriver/src/common/webdriver_handler.dart';
import 'package:webdriver/src/handler/json_wire_handler.dart';
import 'package:webdriver/src/handler/w3c_handler.dart';

import 'web_element.dart';

class Mouse {
  final SyncRequestClient _client;
  final WebDriverHandler _handler;

  Mouse(this._client, this._handler);

  /// Click any mouse button (at the coordinates set by the last moveTo).
  void click([MouseButton button = MouseButton.primary]) {
    _client.send(_handler.mouse.buildClickRequest(button),
        _handler.mouse.parseClickResponse);
  }

  /// Click and hold any mouse button (at the coordinates set by the last
  /// moveTo command).
  void down([MouseButton button = MouseButton.primary]) {
    _client.send(_handler.mouse.buildDownRequest(button),
        _handler.mouse.parseDownResponse);
  }

  /// Releases the mouse button previously held (where the mouse is
  /// currently at).
  void up([MouseButton button = MouseButton.primary]) {
    _client.send(
        _handler.mouse.buildUpRequest(button), _handler.mouse.parseUpResponse);
  }

  /// Double-clicks at the current mouse coordinates (set by moveTo).
  void doubleClick() {
    _client.send(_handler.mouse.buildDoubleClickRequest(),
        _handler.mouse.parseDoubleClickResponse);
  }

  /// Move the mouse.
  ///
  /// If [absolute] is set to true, will move the mouse to the offset relative
  /// to web page's top left corner. This is only supported in W3C webdriver.
  ///
  /// If [element] is specified and [xOffset] and [yOffset] are not, will move
  /// the mouse to the center of the [element].
  ///
  /// If [xOffset] and [yOffset] are specified, will move the mouse that
  /// distance from its current location.
  ///
  /// If all three are specified, the behavior will be different
  /// for W3C and JsonWire. For W3C, it will use [element] center as the
  /// origin, while for JsonWire, it will use [element] top left corner.
  /// To get a consistent behavior across browsers, you can try
  /// [moveToElementCenter] and [moveToElementTopLeft] to specify the origin you
  /// would like to use.
  ///
  /// All other combinations of parameters are illegal.
  ///
  /// Special notes for W3C, if the destination is out of the current viewport,
  /// an 'MoveTargetOutOfBounds' exception will be thrown.
  void moveTo(
      {WebElement element, int xOffset, int yOffset, bool absolute = false}) {
    _client.send(
        _handler.mouse.buildMoveToRequest(
            elementId: element?.id,
            xOffset: xOffset,
            yOffset: yOffset,
            absolute: absolute),
        _handler.mouse.parseMoveToResponse);
  }

  /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
  /// center of [element].
  void moveToElementCenter(WebElement element, {int xOffset, int yOffset}) {
    if (_handler is JsonWireWebDriverHandler) {
      final size = element.size;
      moveTo(
          element: element,
          xOffset: (xOffset ?? 0) + size.width ~/ 2,
          yOffset: (yOffset ?? 0) + size.height ~/ 2);
    } else {
      moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
    }
  }

  /// Moves to [element], with an offset of [xOffset] and [yOffset] based on the
  /// top left corner of [element].
  void moveToElementTopLeft(WebElement element, {int xOffset, int yOffset}) {
    if (_handler is W3cWebDriverHandler) {
      final size = element.size;
      moveTo(
          element: element,
          xOffset: (xOffset ?? 0) - size.width ~/ 2,
          yOffset: (yOffset ?? 0) - size.height ~/ 2);
    } else {
      moveTo(element: element, xOffset: xOffset, yOffset: yOffset);
    }
  }

  /// Moves the mouse away to hide its effect, like hover over element.
  ///
  /// For W3C, the mouse cannot move out of the screen, the workaround would be
  /// to move to somewhere on edge where it's not on any element. You can
  /// configure the location with [w3cXOffset] and [w3cYOffset]. By default,
  /// it's at (100, 0).
  void hide({int w3cXOffset = 100, int w3cYOffset = 0}) =>
      _handler is W3cWebDriverHandler
          ? moveTo(xOffset: w3cXOffset, yOffset: w3cYOffset, absolute: true)
          : moveTo(xOffset: -10000, yOffset: -10000);

  @override
  String toString() => '$_handler.mouse($_client)';

  @override
  int get hashCode => _client.hashCode;

  @override
  bool operator ==(other) =>
      other is Mouse && _handler == other._handler && _client == other._client;
}
