#!/usr/bin/python
# 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()
