# Copyright 2018 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 logging
import os
import time

from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros.chameleon import chameleon
from autotest_lib.client.cros.input_playback import input_playback

_CHECK_TIMEOUT = 20
_GO_TO_CHANGE_BUTTON = 2
_GO_TO_USB_PRINTER = 4
_NOTIF_TITLE = "Successfully printed"
_NOW_PRINTING_STATUS = "Now printing"
_PRINTER_NAME = "HP OfficeJet g55"
_SHORT_WAIT = 2

class platform_PrintJob(test.test):
    """
    E2E test - Chrome is brought up, local pdf file open, print dialog open,
    chameleon gadget driver printer selected and print job executed. The test
    verifies the print job finished successfully.
    """
    version = 1

    def warmup(self):
        """Test setup."""
        # Emulate keyboard to play back shortcuts and navigate.
        # See input_playback README.
        self._player = input_playback.InputPlayback()
        self._player.emulate(input_type='keyboard')
        self._player.find_connected_inputs()


    def cleanup(self):
        if hasattr(self, 'browser'):
            self.browser.close()
        self._player.close()



    def _open_print_dialog(self):
        """Use keyboard shortcut to open print dialog."""
        self._player.blocking_playback_of_default_file(
            input_type='keyboard', filename='keyboard_ctrl+p')
        time.sleep(_SHORT_WAIT)


    def _press_tab(self):
        """Use keyboard shortcut to press Tab."""
        self._player.blocking_playback_of_default_file(
            input_type='keyboard', filename='keyboard_tab')


    def _press_enter(self):
        """Use keyboard shortcut to press Enter."""
        self._player.blocking_playback_of_default_file(
            input_type='keyboard', filename='keyboard_enter')
        time.sleep(_SHORT_WAIT)


    def _check_printer_in_dialog(self):
        """Use autotest_private to read discovered printers.

        @raises: error.TestFail if printer is not found in print dialog list.
        """
        self.cr.autotest_ext.ExecuteJavaScript(
                'window.__printers = null; '
                'chrome.autotestPrivate.getPrinterList(function(printers) {'
                '    window.__printers = printers'
                '});')
        printers = self.cr.autotest_ext.EvaluateJavaScript(
                'window.__printers;')
        logging.info(str(printers))
        printers_number = len(printers)
        if printers_number != 1:
            raise error.TestFail('Bad number of printers: %d' % printers_number)
        if printers[0]['printerName'] != 'Chameleon ' + _PRINTER_NAME+' (USB)':
            raise error.TestFail('Chameleon printer name not found!')
        return printers


    def execute_print_job(self):
        """Using keyboard imput navigate to print dialog and execute a job."""

        # Open dialog and press 'Change...' button
        self._open_print_dialog()
        for x in range(_GO_TO_CHANGE_BUTTON):
            self._press_tab()
        self._press_enter()

        # Navigate to and select the emulated printer
        for x in range(_GO_TO_USB_PRINTER):
            self._press_tab()
        self._press_enter()

        # Check printer is in the peinter's list
        self._check_printer_in_dialog()

        # Send the print job
        self._press_enter()


    def check_notification(self, notification):
        """Polls for successful print job notification"""

        def find_notification(title=None):
            notifications = self.cr.get_visible_notifications()
            if notifications is None:
                return False
            for n in notifications:
                if title in n['title']:
                    return True
            return False

        utils.poll_for_condition(
                condition=lambda: find_notification(notification),
                desc='Notification %s NOT found' % notification,
                timeout=_CHECK_TIMEOUT, sleep_interval=_SHORT_WAIT)


    def navigate_to_pdf(self):
        """Navigate to the pdf page to print"""
        self.cr.browser.platform.SetHTTPServerDirectories(self.bindir)
        tab = self.cr.browser.tabs.New()
        pdf_path = os.path.join(self.bindir, 'to_print.pdf')
        tab.Navigate(self.cr.browser.platform.http_server.UrlOf(pdf_path))
        tab.WaitForDocumentReadyStateToBeInteractiveOrBetter(
                timeout=_CHECK_TIMEOUT);


    def run_once(self, host, args):
        """Run the test."""
        chameleon_board = chameleon.create_chameleon_board(host.hostname, args)
        chameleon_board.setup_and_reset(self.outputdir)
        usb_printer = chameleon_board.get_usb_printer()
        usb_printer.SetPrinterModel(1008, 17, _PRINTER_NAME)

        with chrome.Chrome(autotest_ext=True,
                           init_network_controller=True) as self.cr:
            self.navigate_to_pdf()
            usb_printer.Plug()
            self.execute_print_job()
            usb_printer.StartCapturingPrinterData()
            self.check_notification('Now printing')
            self.check_notification('Successfully printed')
            usb_printer.StopCapturingPrinterData()
            usb_printer.Unplug()