# Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import os
import logging

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros import touch_playback_test_base


class touch_MouseScroll(touch_playback_test_base.touch_playback_test_base):
    """Plays back mouse scrolls and checks for correct page movement."""
    version = 1

    _MOUSE_DESCRIPTION = 'amazon_mouse.prop'
    _APPLE_MOUSE_DES = 'apple_mouse.prop'
    _EXPECTED_RANGE_1 = [9, 11] # Expected value of one scroll wheel turn.
    _EXPECTED_DIRECTION = {'down': 1, 'up': -1, 'right': 1, 'left': -1}
    _TOLLERANCE = 4 # Fast scroll should go at least X times slow scroll.


    def _get_scroll_delta(self, name, expected_direction, scroll_vertical=True):
        """Playback the given test and return the amount the page moved.

        @param name: name of test filename.
        @param expected_direction: an integer that is + for down and - for up.
        @param scroll_vertical: True for vertical scroll,
                                False for horizontal scroll.

        @raise: TestFail if scrolling did not occur in expected direction.

        """
        self._events.clear_previous_events()
        self._events.set_default_scroll_position(scroll_vertical)
        start_scroll = self._events.get_scroll_position(scroll_vertical)
        self._events.clear_previous_events()

        self._playback(self._gest_file_path[name], touch_type='mouse')

        self._events.wait_for_events_to_complete()
        end_scroll = self._events.get_scroll_position(scroll_vertical)
        delta = end_scroll - start_scroll
        logging.info('Test %s: saw scroll delta of %d.  Expected direction %d.',
                     name, delta, expected_direction)

        if delta * expected_direction < 0:
            self._events.log_events()
            raise error.TestFail('Scroll was in wrong direction!  Delta '
                                 'for %s was %d.' % (name, delta))
        return delta


    def _verify_single_tick(self, direction, scroll_vertical=True):
        """Verify that using the scroll wheel goes the right distance.

        Expects a file (playback gesture file) named direction + '_1'.

        @param direction: string indicating direction up, down, right and left.
        @param scroll_vertical: scroll_vertical is True for vertical scroll
                                else False

        """
        name = direction + '_1'
        expected_direction = self._EXPECTED_DIRECTION[direction]
        expected_range = sorted([x * expected_direction for x in
            self._EXPECTED_RANGE_1])
        delta = self._get_scroll_delta(name, expected_direction,
                                       scroll_vertical)

        if not expected_range[0] <= delta <= expected_range[1]:
            self._events.log_events()
            raise error.TestFail(
                'One tick scroll was wrong size: '
                'direction=%s, actual=%d, expected=[%d, %d]' %
                 (direction, delta, expected_range[0], expected_range[1]))


    def _verify_fast_vs_slow(self, direction, scroll_vertical=True):
        """Verify that fast scrolling goes farther than slow scrolling.

        Expects files (playback gesture file) named direction + '_slow'
        and direction + '_fast'.

        @param direction: string indicating direction up, down, right and left.
        @param scroll_vertical: True for vertical scroll,
                                False for horizontal scroll.

        """
        slow = direction + '_slow'
        fast = direction + '_fast'
        expected = self._EXPECTED_DIRECTION[direction]
        slow_delta = self._get_scroll_delta(slow, expected, scroll_vertical)
        fast_delta = self._get_scroll_delta(fast, expected, scroll_vertical)

        if abs(fast_delta) < self._TOLLERANCE * abs(slow_delta):
            self._events.log_events()
            raise error.TestFail('Fast scroll should be much farther than '
                                 'slow! (%s).  %d vs. %d.' %
                                  (direction, slow_delta, fast_delta))


    def run_once(self):
        """Entry point of this test."""

        # Link path for files to playback on DUT.
        self._gest_file_path = {}
        gestures_dir = os.path.join(self.bindir, 'gestures')
        for filename in os.listdir(gestures_dir):
            self._gest_file_path[filename] = os.path.join(gestures_dir,
                                                          filename)

        with chrome.Chrome(init_network_controller=True) as cr:
            # Open test page.
            self._open_events_page(cr)
            self._events.expand_page()
            self._events.set_prevent_defaults(False)

            # Emulate mouse with vertical scroll feature.
            mouse_file = os.path.join(self.bindir, self._MOUSE_DESCRIPTION)
            self._emulate_mouse(property_file=mouse_file)
            if not self._has_mouse:
                raise error.TestError('No USB mouse found on this device.')
            # In test page, position cursor to center.
            self._blocking_playback(self._gest_file_path['center_cursor'],
                                    touch_type='mouse')
            self._events.wait_for_events_to_complete()

            # Test vertical scrolling.
            for direction in ['down', 'up']:
                self._verify_single_tick(direction)
                self._verify_fast_vs_slow(direction)

            # Emulate mouse with horizontal scroll feature.
            apple_mouse_file = os.path.join(self.bindir, self._APPLE_MOUSE_DES)
            self._emulate_mouse(property_file=apple_mouse_file)
            if not self._has_mouse:
                raise error.TestError('No USB mouse found on this device.')

            # Test horizontal scrolling.
            for direction in ['right', 'left']:
                self._verify_single_tick(direction, scroll_vertical=False)
                self._verify_fast_vs_slow(direction, scroll_vertical=False)
