# Copyright 2015 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 base64
import mock_lorgnette
import os

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


class documentscan_AppTestWithFakeLorgnette(
        touch_playback_test_base.touch_playback_test_base):
    """ Test that an extension using the DocumentScan Chrome API can
        successfully retrieve a scanned document from a mocked version
        of the lorgnette daemon.
    """
    version = 1

    # Application ID of the test scan application.
    _APP_ID = 'mljeglgkknlanoeffbeehogdhkhnaidk'

    # Document to open in order to launch the scan application.
    _APP_DOCUMENT = 'scan.html'

    # Window ID that references the scan application window.
    _APP_WINDOW_ID = 'ChromeApps-Sample-Document-Scan'

    # Element within the scan application document that contains image scans.
    _APP_SCANNED_IMAGE_ELEMENT = 'scannedImages'

    # Description of the fake mouse we add to the system.
    _MOUSE_DESCRIPTION = 'amazon_mouse.prop'

    # This input file was created as follows:
    #  - Insert USB mouse (in this case the Amazon mouse)
    #  - head /sys/class/input/*/name | grep -iB1 mouse
    #    This will give you the /sys/class/inputXX for the mouse.
    #  - evemu-record /dev/input/eventXX -1 > /tmp/button_click.event
    #    Move the mouse diagonally upwards to the upper left, move
    #    down and right a bit then click.
    _PLAYBACK_FILE = 'button_click.event'

    # Image file to serve up to Chrome in response to a scan request.
    _IMAGE_FILENAME = 'lorgnette-test.png'

    # Expected prefix for the SRC tag of the scanned images.
    _BASE64_IMAGE_HEADER = 'data:image/png;base64,'

    def _play_events(self, event_filename):
        """Simulate mouse events since the Chrome API enforces that
        the scan action come from a user gesture.

        @param event_filename string filename containing events to play back
        """

        file_path = os.path.join(self.bindir, event_filename)
        self._blocking_playback(file_path, touch_type='mouse')


    def _launch_app(self, chrome_instance):
        """Launches the sample scanner Chrome app.

        @param chrome_instance object of type chrome.Chrome
        """

        self._extension = chrome_instance.get_extension(self._extension_path)

        # TODO(pstew): chrome.management.launchApp() would have been
        # ideal here, but is not available even after adding the
        # "management" permission to the app.  Instead, we perform
        # the launch action of the extension directly.
        cmd = '''
            chrome.app.window.create('%s', {
              singleton: true,
              id: '%s',
              state: 'fullscreen'
            });
        ''' % (self._APP_DOCUMENT, self._APP_WINDOW_ID)
        self._extension.ExecuteJavaScript(cmd)


    def _query_scan_element(self, query):
        """Queries the "scannedImages" element within the app window.

        @param query string javascript query to execute on the DIV element.
        """

        cmd = '''
           app_window = chrome.app.window.get('%s');
           element = app_window.contentWindow.document.getElementById('%s');
           element.%s;
        ''' % (self._APP_WINDOW_ID, self._APP_SCANNED_IMAGE_ELEMENT, query)
        return self._extension.EvaluateJavaScript(cmd)


    def _get_scan_count(self):
        """Counts the number of successful scanned images displayed.

        @param chrome_instance object of type chrome.Chrome
        """

        result = self._query_scan_element('childNodes.length')

        # Subtract 1 for the text node member of the DIV element.
        return int(result) - 1


    def _validate_image_data(self, expected_image_data):
        """Validates that the scanned image displayed by the app is the same
        as the image provided by the fake lorgnette daemon.
        """

        image_src = self._query_scan_element('childNodes[0].src')
        if not image_src.startswith(self._BASE64_IMAGE_HEADER):
            raise error.TestError(
                    'Image SRC does not start with base64 data header: %s' %
                    image_src)

        base64_data = image_src[len(self._BASE64_IMAGE_HEADER):]
        data = base64.b64decode(base64_data)
        if expected_image_data != data:
            raise error.TestError('Image data from tag is not the same as '
                                  'the test image data')


    def _validate_mock_method_calls(self, calls):
        """Validate the method calls made on the lorgnette mock instance.

        @param calls list of MethodCall named tuples from mock lorgnette.
        """

        if len(calls) != 2:
            raise error.TestError('Expected 2 method calls but got: %r' % calls)

        for index, method_name in enumerate(['ListScanners', 'ScanImage']):
            if calls[index].method != method_name:
                raise error.TestError('Call #%d was %s instead of expected %s' %
                                      (index, calls[index].method, method_name))


    def run_once(self):
        """Entry point of this test."""
        mouse_file = os.path.join(self.bindir, self._MOUSE_DESCRIPTION)
        self._emulate_mouse(property_file=mouse_file)

        self._extension_path = os.path.join(os.path.dirname(__file__),
                                            'document_scan_test_app')

        with chrome.Chrome(extension_paths=[self._extension_path],
                           init_network_controller=True) as cr:
            img = os.path.join(self.bindir, self._IMAGE_FILENAME)
            with mock_lorgnette.MockLorgnette(img) as lorgnette_instance:
                self._launch_app(cr)

                self._play_events(self._PLAYBACK_FILE)

                scan_count = self._get_scan_count()
                if scan_count != 1:
                    raise error.TestError('Scan count is %d instead of 1' %
                                          scan_count)

                self._validate_image_data(lorgnette_instance.image_data)
                self._validate_mock_method_calls(
                        lorgnette_instance.get_method_calls())
