#!/usr/bin/python2
# Copyright (c) 2012 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.

"""This module sets up the system for the touch device firmware test suite."""

import getopt
import glob
import logging
import os
import sys

import common
import cros_gs
import firmware_utils

# TODO(josephsih): remove this hack when not relying on pygtk.
# The pygtk related stuffs are needed by firmware_window below.
if not firmware_utils.install_pygtk():
    sys.exit(1)

import firmware_window
import keyboard_device
import mtb
import test_conf as conf
import test_flow
import touch_device
import validators

from common_util import print_and_exit
from firmware_constants import MODE, OPTIONS
from report_html import ReportHtml


def _display_test_result(report_html_name, flag_skip_html):
    """Display the test result html doc using telemetry."""
    if not flag_skip_html and os.path.isdir('/usr/local/telemetry'):
        import chrome

        base_url = os.path.basename(report_html_name)
        url = os.path.join('file://' + conf.docroot, base_url)
        logging.info('Navigate to the URL: %s', url)

        # Launch a browser to display the url.
        print 'Display the html test report on the browser.'
        print 'This may take a while...\n'
        chrome.Chrome().browser.tabs[0].Navigate(url)
    else:
        print 'You can look up the html test result in %s' % report_html_name


class firmware_TouchMTB:
    """Set up the system for touch device firmware tests."""

    def __init__(self, options):
        self.options = options

        self.test_version = 'test_' + self._get_test_version()

        # Get the board name
        self._get_board()

        # We may need to use a device description file to create a fake device
        # for replay purpose.
        self._get_device_description_file()

        # Create the touch device
        # If you are going to be testing a touchscreen, set it here
        self.touch_device = touch_device.TouchDevice(
            is_touchscreen=options[OPTIONS.TOUCHSCREEN],
            device_description_file=self.device_description_file)
        self._check_device(self.touch_device)
        validators.init_base_validator(self.touch_device)

        # Create the keyboard device.
        self.keyboard = keyboard_device.KeyboardDevice()
        self._check_device(self.keyboard)

        # Get the MTB parser.
        self.parser = mtb.MtbParser()

        # Create a simple gtk window.
        self._get_screen_size()
        self._get_touch_device_window_geometry()
        self._get_prompt_frame_geometry()
        self._get_result_frame_geometry()
        self.win = firmware_window.FirmwareWindow(
                size=self.screen_size,
                prompt_size=self.prompt_frame_size,
                image_size=self.touch_device_window_size,
                result_size=self.result_frame_size)

        mode = options[OPTIONS.MODE]
        if options[OPTIONS.RESUME]:
            # Use the firmware version of the real touch device for recording.
            firmware_version = self.touch_device.get_firmware_version()
            self.log_dir = options[OPTIONS.RESUME]
        elif options[OPTIONS.REPLAY]:
            # Use the firmware version of the specified logs for replay.
            self.log_dir = options[OPTIONS.REPLAY]
            fw_str, date = firmware_utils.get_fw_and_date(self.log_dir)
            _, firmware_version = fw_str.split(conf.fw_prefix)
        else:
            # Use the firmware version of the real touch device for recording.
            firmware_version = self.touch_device.get_firmware_version()
            self.log_dir = firmware_utils.create_log_dir(firmware_version, mode)

        # Save the device description file for future replay purpose if needed.
        if not (self.options[OPTIONS.REPLAY] or self.options[OPTIONS.RESUME]):
            self._save_device_description_file()

        # Create the HTML report object and the output object to print messages
        # on the window and to print the results in the report.
        self._create_report_name(mode, firmware_version)
        self.report_html = ReportHtml(self.report_html_name,
                                      self.screen_size,
                                      self.touch_device_window_size,
                                      conf.score_colors,
                                      self.test_version)
        self.output = firmware_utils.Output(self.log_dir,
                                            self.report_name,
                                            self.win, self.report_html)

        # Get the test_flow object which will guide through the gesture list.
        self.test_flow = test_flow.TestFlow(self.touch_device_window_geometry,
                                            self.touch_device,
                                            self.keyboard,
                                            self.win,
                                            self.parser,
                                            self.output,
                                            self.test_version,
                                            self.board,
                                            firmware_version,
                                            options)

        # Register some callback functions for firmware window
        self.win.register_callback('expose_event',
                                   self.test_flow.init_gesture_setup_callback)

        # Register a callback function to watch keyboard input events.
        # This is required because the set_input_focus function of a window
        # is flaky maybe due to problems of the window manager.
        # Hence, we handle the keyboard input at a lower level.
        self.win.register_io_add_watch(self.test_flow.user_choice_callback,
                                       self.keyboard.system_device)

        # Stop power management so that the screen does not dim during tests
        firmware_utils.stop_power_management()

    def _check_device(self, device):
        """Check if a device has been created successfully."""
        if not device.exists():
            logging.error('Cannot find device_node.')
            exit(1)

    def _get_test_version(self):
        """Get the test suite version number."""
        if not os.path.isfile(conf.version_filename):
            err_msg = ('Error: cannot find the test version file: %s\n\n'
                       'Perform the following steps in chroot to install '
                       'the test suite correctly:\n'
                       'Step 1: (cr) $ cd ~/trunk/src/scripts\n'
                       'Step 2: (cr) $ test_that --autotest_dir '
                       '~/trunk/src/third_party/autotest/files '
                       '$MACHINE_IP firmware_TouchMTBSetup\n')
            print err_msg % conf.version_filename
            sys.exit(1)

        with open(conf.version_filename) as version_file:
            return version_file.read()

    def _get_board(self):
        """Get the board.

        If this is in replay mode, get the board from the replay directory.
        Otherwise, get the board name from current chromebook machine.
        """
        replay_dir = self.options[OPTIONS.REPLAY]
        if replay_dir:
            self.board = firmware_utils.get_board_from_directory(replay_dir)
            if self.board is None:
                msg = 'Error: cannot get the board from the replay directory %s'
                print_and_exit(msg % replay_dir)
        else:
            self.board = firmware_utils.get_board()
        print '      board: %s' % self.board

    def _get_device_ext(self):
        """Set the file extension of the device description filename to
        'touchscreen' if it is a touchscreen; otherwise, set it to 'touchpad'.
        """
        return ('touchscreen' if self.options[OPTIONS.TOUCHSCREEN] else
                'touchpad')

    def _get_device_description_file(self):
        """Get the device description file for replay purpose.

        Get the device description file only when it is in replay mode and
        the system DEVICE option is not specified.

        The priority to locate the device description file:
        (1) in the directory specified by the REPLAY option,
        (2) in the tests/device/ directory

        A device description file name looks like "link.touchpad"
        """
        self.device_description_file = None
        # Replay without using the system device. So use a mocked device.
        if self.options[OPTIONS.REPLAY] and not self.options[OPTIONS.DEVICE]:
            device_ext = self._get_device_ext()
            board = self.board
            descriptions = [
                # (1) Try to find the device description in REPLAY directory.
                (self.options[OPTIONS.REPLAY], '*.%s' % device_ext),
                # (2) Try to find the device description in tests/device/
                (conf.device_description_dir, '%s.%s' % (board, device_ext),)
            ]

            for description_dir, description_pattern in descriptions:
                files = glob.glob(os.path.join(description_dir,
                                               description_pattern))
                if files:
                    self.device_description_file = files[0]
                    break
            else:
                msg = 'Error: cannot find the device description file.'
                print_and_exit(msg)
        print '      device description file: %s' % self.device_description_file

    def _save_device_description_file(self):
        """Save the device description file for future replay."""
        filename = '%s.%s' % (self.board, self._get_device_ext())
        filepath = os.path.join(self.log_dir, filename)
        if not self.touch_device.save_device_description_file(
                filepath, self.board):
            msg = 'Error: fail to save the device description file: %s'
            print_and_exit(msg % filepath)

    def _create_report_name(self, mode, firmware_version):
        """Create the report names for both plain-text and html files.

        A typical html file name looks like:
            touch_firmware_report-lumpy-fw_11.25-20121016_080924.html
        """
        firmware_str = conf.fw_prefix + firmware_version
        curr_time = firmware_utils.get_current_time_str()
        fname = conf.filename.sep.join([conf.report_basename,
                                        self.board,
                                        firmware_str,
                                        mode,
                                        curr_time])
        self.report_name = os.path.join(self.log_dir, fname)
        self.report_html_name = self.report_name + conf.html_ext

    def _get_screen_size(self):
        """Get the screen size."""
        self.screen_size = firmware_utils.get_screen_size()

    def _get_touch_device_window_geometry(self):
        """Get the preferred window geometry to display mtplot."""
        display_ratio = 0.7
        self.touch_device_window_geometry = \
                self.touch_device.get_display_geometry(
                self.screen_size, display_ratio)
        self.touch_device_window_size = self.touch_device_window_geometry[0:2]

    def _get_prompt_frame_geometry(self):
        """Get the display geometry of the prompt frame."""
        (_, wint_height, _, _) = self.touch_device_window_geometry
        screen_width, screen_height = self.screen_size
        win_x = 0
        win_y = 0
        win_width = screen_width
        win_height = screen_height - wint_height
        self.winp_geometry = (win_x, win_y, win_width, win_height)
        self.prompt_frame_size = (win_width, win_height)

    def _get_result_frame_geometry(self):
        """Get the display geometry of the test result frame."""
        (wint_width, wint_height, _, _) = self.touch_device_window_geometry
        screen_width, _ = self.screen_size
        win_width = screen_width - wint_width
        win_height = wint_height
        self.result_frame_size = (win_width, win_height)

    def main(self):
        """A helper to enter gtk main loop."""
        # Enter the window event driven mode.
        fw.win.main()

        # Resume the power management.
        firmware_utils.start_power_management()

        flag_skip_html = self.options[OPTIONS.SKIP_HTML]
        try:
            _display_test_result(self.report_html_name, flag_skip_html)
        except Exception, e:
            print 'Warning: cannot display the html result file: %s\n' % e
            print ('You can access the html result file: "%s"\n' %
                   self.report_html_name)
        finally:
            print 'You can upload all data in the latest result directory:'
            print '  $ DISPLAY=:0 OPTIONS="-u latest" python main.py\n'
            print ('You can also upload any test result directory, e.g., '
                   '"20130702_063631-fw_1.23-manual", in "%s"' %
                   conf.log_root_dir)
            print ('  $ DISPLAY=:0 OPTIONS="-u 20130702_063631-fw_11.23-manual"'
                   ' python main.py\n')

            if self.options[OPTIONS.MODE] == MODE.NOISE:
                print ('You can generate a summary of the extended noise test_flow '
                       'by copying the html report to your computer and running '
                       'noise_summary.py, located in '
                       '~/trunk/src/third_party/autotest/files/client/site_tests/firmware_TouchMTB/')


def upload_to_gs(log_dir):
    """Upload the gesture event files specified in log_dir to Google cloud
    storage server.

    @param log_dir: the log directory of which the gesture event files are
            to be uploaded to Google cloud storage server
    """
    # Set up gsutil package.
    # The board argument is used to locate the proper bucket directory
    gs = cros_gs.CrosGs(firmware_utils.get_board())

    log_path = os.path.join(conf.log_root_dir, log_dir)
    if not os.path.isdir(log_path):
        print_and_exit('Error: the log path "%s" does not exist.' % log_path)

    print 'Uploading "%s" to %s ...\n' % (log_path, gs.bucket)
    try:
        gs.upload(log_path)
    except Exception, e:
        msg = 'Error in uploading event files in %s: %s.'
        print_and_exit(msg % (log_path, e))


def _usage_and_exit():
    """Print the usage of this program."""
    print 'Usage: $ DISPLAY=:0 [OPTIONS="options"] python %s\n' % sys.argv[0]
    print 'options:'
    print '  -d, --%s' % OPTIONS.DEVICE
    print '        use the system device for replay'
    print '  -h, --%s' % OPTIONS.HELP
    print '        show this help'
    print '  -i, --%s iterations' % OPTIONS.ITERATIONS
    print '        specify the number of iterations'
    print '  -f, --%s' % OPTIONS.FNGENERATOR
    print '        Indicate that (despite not having a touchbot) there is a'
    print '        function generator attached for the noise tests'
    print '  -m, --%s mode' % OPTIONS.MODE
    print '        specify the gesture playing mode'
    print '        mode could be one of the following options'
    print '            calibration: conducting pressure calibration'
    print '            complete: all gestures including those in ' \
                                'both manual mode and robot mode'
    print '            manual: all gestures minus gestures in robot mode'
    print '            noise: an extensive, 4 hour noise test'
    print '            robot: using robot to perform gestures automatically'
    print '            robot_sim: robot simulation, for developer only'
    print '  --%s log_dir' % OPTIONS.REPLAY
    print '        Replay the gesture files and get the test results.'
    print '        log_dir is a log sub-directory in %s' % conf.log_root_dir
    print '  --%s log_dir' % OPTIONS.RESUME
    print '        Resume recording the gestures files in the log_dir.'
    print '        log_dir is a log sub-directory in %s' % conf.log_root_dir
    print '  -s, --%s' % OPTIONS.SIMPLIFIED
    print '        Use one variation per gesture'
    print '  --%s' % OPTIONS.SKIP_HTML
    print '        Do not show the html test result.'
    print '  -t, --%s' % OPTIONS.TOUCHSCREEN
    print '        Use the touchscreen instead of a touchpad'
    print '  -u, --%s log_dir' % OPTIONS.UPLOAD
    print '        Upload the gesture event files in the specified log_dir '
    print '        to Google cloud storage server.'
    print '        It uploads results that you already have from a previous run'
    print '        without re-running the test.'
    print '        log_dir could be either '
    print '        (1) a directory in %s' % conf.log_root_dir
    print '        (2) a full path, or'
    print '        (3) the default "latest" directory in %s if omitted' % \
                   conf.log_root_dir
    print
    print 'Example:'
    print '  # Use the robot to perform 3 iterations of the robot gestures.'
    print '  $ DISPLAY=:0 OPTIONS="-m robot_sim -i 3" python main.py\n'
    print '  # Perform 1 iteration of the manual gestures.'
    print '  $ DISPLAY=:0 OPTIONS="-m manual" python main.py\n'
    print '  # Perform 1 iteration of all manual and robot gestures.'
    print '  $ DISPLAY=:0 OPTIONS="-m complete" python main.py\n'
    print '  # Perform pressure calibration.'
    print '  $ DISPLAY=:0 OPTIONS="-m calibration" python main.py\n'
    print '  # Use the robot to perform a latency test with Quickstep'
    print '  $ DISPLAY=:0 OPTIONS="-m quickstep" python main.py\n'
    print '  # Use the robot to perform an extensive, 4 hour noise test'
    print '  $ DISPLAY=:0 OPTIONS="-m noise" python main.py\n'
    print '  # Replay the gesture files in the latest log directory.'
    print '  $ DISPLAY=:0 OPTIONS="--replay latest" python main.py\n'
    example_log_dir = '20130226_040802-fw_1.2-manual'
    print ('  # Replay the gesture files in %s/%s with a mocked device.' %
            (conf.log_root_dir, example_log_dir))
    print '  $ DISPLAY=:0 OPTIONS="--replay %s" python main.py\n' % \
            example_log_dir
    print ('  # Replay the gesture files in %s/%s with the system device.' %
            (conf.log_root_dir, example_log_dir))
    print ('  $ DISPLAY=:0 OPTIONS="--replay %s -d" python main.py\n' %
            example_log_dir)
    print '  # Resume recording the gestures in the latest log directory.'
    print '  $ DISPLAY=:0 OPTIONS="--resume latest" python main.py\n'
    print '  # Resume recording the gestures in %s/%s.' % (conf.log_root_dir,
                                                           example_log_dir)
    print '  $ DISPLAY=:0 OPTIONS="--resume %s" python main.py\n' % \
            example_log_dir
    print ('  # Upload the gesture event files specified in the log_dir '
             'to Google cloud storage server.')
    print ('  $ DISPLAY=:0 OPTIONS="-u 20130701_020120-fw_11.23-complete" '
           'python main.py\n')
    print ('  # Upload the gesture event files in the "latest" directory '
           'to Google cloud storage server.')
    print '  $ DISPLAY=:0 OPTIONS="-u latest" python main.py\n'

    sys.exit(1)


def _parsing_error(msg):
    """Print the usage and exit when encountering parsing error."""
    print 'Error: %s' % msg
    _usage_and_exit()


def _parse_options():
    """Parse the options.

    Note that the options are specified with environment variable OPTIONS,
    because pyauto seems not compatible with command line options.
    """
    # Set the default values of options.
    options = {OPTIONS.DEVICE: False,
               OPTIONS.FNGENERATOR: False,
               OPTIONS.ITERATIONS: 1,
               OPTIONS.MODE: MODE.MANUAL,
               OPTIONS.REPLAY: None,
               OPTIONS.RESUME: None,
               OPTIONS.SIMPLIFIED: False,
               OPTIONS.SKIP_HTML: False,
               OPTIONS.TOUCHSCREEN: False,
               OPTIONS.UPLOAD: None,
    }

    # Get the command line options or get the options from environment OPTIONS
    options_list = sys.argv[1:] or os.environ.get('OPTIONS', '').split()
    if not options_list:
        return options

    short_opt = 'dfhi:m:stu:'
    long_opt = [OPTIONS.DEVICE,
                OPTIONS.FNGENERATOR,
                OPTIONS.HELP,
                OPTIONS.ITERATIONS + '=',
                OPTIONS.MODE + '=',
                OPTIONS.REPLAY + '=',
                OPTIONS.RESUME + '=',
                OPTIONS.SIMPLIFIED,
                OPTIONS.SKIP_HTML,
                OPTIONS.TOUCHSCREEN,
                OPTIONS.UPLOAD + '=',
    ]
    try:
        opts, args = getopt.getopt(options_list, short_opt, long_opt)
    except getopt.GetoptError, err:
        _parsing_error(str(err))

    for opt, arg in opts:
        if opt in ('-d', '--%s' % OPTIONS.DEVICE):
            options[OPTIONS.DEVICE] = True
        if opt in ('-f', '--%s' % OPTIONS.FNGENERATOR):
            options[OPTIONS.FNGENERATOR] = True
        elif opt in ('-h', '--%s' % OPTIONS.HELP):
            _usage_and_exit()
        elif opt in ('-i', '--%s' % OPTIONS.ITERATIONS):
            if arg.isdigit():
                options[OPTIONS.ITERATIONS] = int(arg)
            else:
                _usage_and_exit()
        elif opt in ('-m', '--%s' % OPTIONS.MODE):
            arg = arg.lower()
            if arg in MODE.GESTURE_PLAY_MODE:
                options[OPTIONS.MODE] = arg
            else:
                print 'Warning: -m should be one of %s' % MODE.GESTURE_PLAY_MODE
        elif opt in ('--%s' % OPTIONS.REPLAY, '--%s' % OPTIONS.RESUME):
            log_dir = os.path.join(conf.log_root_dir, arg)
            if os.path.isdir(log_dir):
                # opt could be either '--replay' or '--resume'.
                # We would like to strip off the '-' on the left hand side.
                options[opt.lstrip('-')] = log_dir
            else:
                print 'Error: the log directory "%s" does not exist.' % log_dir
                _usage_and_exit()
        elif opt in ('-s', '--%s' % OPTIONS.SIMPLIFIED):
            options[OPTIONS.SIMPLIFIED] = True
        elif opt in ('--%s' % OPTIONS.SKIP_HTML,):
            options[OPTIONS.SKIP_HTML] = True
        elif opt in ('-t', '--%s' % OPTIONS.TOUCHSCREEN):
            options[OPTIONS.TOUCHSCREEN] = True
        elif opt in ('-u', '--%s' % OPTIONS.UPLOAD):
            upload_to_gs(arg)
            sys.exit()
        else:
            msg = 'This option "%s" is not supported.' % opt
            _parsing_error(opt)

    print 'Note: the %s mode is used.' % options[OPTIONS.MODE]
    return options


if __name__ == '__main__':
    options = _parse_options()
    fw = firmware_TouchMTB(options)
    fw.main()
