# -*- coding: utf-8 -*-
# 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.

# TODO(sheckylin): Refactor the code with the new HTML5 framework.

# Import guard for OpenCV.
try:
    import cv
    import cv2
except ImportError:
    pass

import gtk
import logging
import numpy as np
import os
import pprint
import re
import serial
import StringIO
import time

import autotest_lib.client.cros.camera.perf_tester as camperf

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.cros import factory
from autotest_lib.client.cros.factory import ui as ful
from autotest_lib.client.cros.factory import leds
from autotest_lib.client.cros.factory.media_util import MediaMonitor
from autotest_lib.client.cros.factory.media_util import MountedMedia
from autotest_lib.client.cros.rf.config import PluggableConfig
from autotest_lib.client.cros import tty

_MESSAGE_USB = (
    'Please insert the usb stick to load parameters.\n'
    '請插入usb以讀取測試參數\n')
_MESSAGE_PREPARE_MACHINE = (
    'Please put the machine in the fixture and connect the keyboard.\n'
    'Then press ENTER.\n'
    '請將待測機器放入盒中並連接鍵盤\n'
    '備妥後按ENTER\n')
_MESSAGE_PREPARE_PANEL = (
    'Please connect the next AB panel.\n'
    'Then press ENTER to scan the barcode.\n'
    '請連接下一塊AB Panel\n'
    '備妥後按ENTER掃描序號\n')
_MESSAGE_PREPARE_CAMERA = (
    'Make sure the camera is connected\n'
    'Then press ENTER to proceed, TAB to skip.\n'
    '確定 攝像頭 連接完成\n'
    '備妥後按ENTER繼續, 或按TAB跳過\n')
_MESSAGE_PREPARE_ALS = (
    'Make sure the light sensor is connected\n'
    'Then press ENTER to proceed, TAB to skip.\n'
    '確定 光感測器 連接完成\n'
    '備妥後按ENTER繼續, 或按TAB跳過\n')
_MESSAGE_RESULT_TAB_ABONLY = (
    'Results are listed below.\n'
    'Please disconnect the panel and press ENTER to write log.\n'
    '測試結果顯示如下\n'
    '請將AB Panel移除, 並按ENTER寫入測試結果\n')
_MESSAGE_RESULT_TAB_FULL = (
    'Results are listed below.\n'
    'Please disconnect the machine and press ENTER to write log.\n'
    '測試結果顯示如下\n'
    '請將測試機器移除, 並按ENTER寫入測試結果\n')

_TEST_SN_NUMBER = 'TEST-SN-NUMBER'
_LABEL_SIZE = (300, 30)

# Test type constants:
_TEST_TYPE_AB = 'AB'
_TEST_TYPE_FULL = 'Full'

# Content type constants:
_CONTENT_IMG = 'image'
_CONTENT_TXT = 'text'

def make_prepare_widget(message, on_key_enter, on_key_tab=None):
    """Returns a widget that display the message and bind proper functions."""
    widget = gtk.VBox()
    widget.add(ful.make_label(message))
    def key_release_callback(widget, event):
        if event.keyval == gtk.keysyms.Tab:
            if on_key_tab is not None:
                return on_key_tab()
        elif event.keyval == gtk.keysyms.Return:
            return on_key_enter()
    widget.key_callback = key_release_callback
    return widget


class ALS():
    '''Class to interface the ambient light sensor over iio.'''

    # Default device paths.
    _VAL_DEV_PATH = '/sys/bus/iio/devices/iio:device0/illuminance0_input'
    _SCALE_DEV_PATH = '/sys/bus/iio/devices/iio:device0/illuminance0_calibscale'

    # Default min delay seconds.
    _DEFAULT_MIN_DELAY = 0.178

    def __init__(self, val_path=_VAL_DEV_PATH,
                 scale_path=_SCALE_DEV_PATH):
        self.detected = True
        if (not os.path.isfile(val_path) or
            not os.path.isfile(scale_path)):
            self.detected = False
            return
        self.val_path = val_path
        self.scale_path = scale_path

    def _read(self, delay=None, samples=1):
        '''Read the light sensor value.

        Args:
            delay: Delay between samples in seconds. 0 means as fast as
                   possible.
            samples: Total samples to read.

        Returns:
            The light sensor values in a list.
        '''
        if samples < 1:
            samples = 1
        if delay is None:
            delay = self._DEFAULT_MIN_DELAY

        buf = []
        for dummy in range(samples):
            fd = open(self.val_path)
            buf.append(int(fd.readline().rstrip()))
            fd.close()
            time.sleep(delay)

        return buf

    def read_mean(self, delay=None, samples=1):
        if not self.detected:
            return None

        buf = self._read(delay, samples)
        return sum(buf) / len(buf)

    def get_scale_factor(self):
        if not self.detected:
            return None

        fd = open(self.scale_path)
        s = int(fd.readline().rstrip())
        fd.close()
        return s


class FixtureException(Exception):
  pass


class Fixture():
    '''Class for communication with the test fixture.'''

    def __init__(self, params):
        # Setup the serial port communication.
        tty_path = tty.find_tty_by_driver(params['driver'])
        self.fixture = serial.Serial(port=tty_path,
                                     **params['serial_params'])
        self.fixture.flush()

        # Load parameters.
        self.serial_delay = params['serial_delay']
        self.light_delay = params['light_delay']
        self.light_seq = params['light_seq']
        self.fixture_echo = params['echo']
        self.light_off = params['off']

    def send(self, msg):
        '''Send control messages to the fixture.'''
        for c in msg:
            self.fixture.write(str(c))
            self.fixture.flush()
            # The fixture needs some time to process each incoming character.
            time.sleep(self.serial_delay)

    def read(self):
        return self.fixture.read(self.fixture.inWaiting())

    def assert_success(self):
        '''Check if the returned value from the fixture is OK.'''
        ret = self.read()
        if not re.search(self.fixture_echo, ret):
            raise FixtureException('The communication with fixture was broken')

    def set_light(self, idx):
        self.send(self.light_seq[idx])

    def turn_off_light(self):
        self.send(self.light_off)

    def wait_for_light_switch(self):
        time.sleep(self.light_delay)


class factory_CameraPerformanceAls(test.test):
    version = 1
    preserve_srcdir = True

    # OpenCV will automatically search for a working camera device if we use
    # the index -1.
    _DEVICE_INDEX = -1
    _TEST_CHART_FILE = 'test_chart.png'
    _TEST_SAMPLE_FILE = 'sample.png'

    # States for the state machine.
    _STATE_INITIAL = -1
    _STATE_WAIT_USB = 0
    _STATE_PREPARE_MACHINE = 1
    _STATE_ENTERING_SN = 2
    _STATE_PREPARE_CAMERA = 3
    _STATE_PREPARE_ALS = 4
    _STATE_RESULT_TAB = 5

    # Status in the final result tab.
    _STATUS_NAMES = ['sn', 'cam_stat', 'cam_vc', 'cam_ls', 'cam_mtf',
                     'als_stat', 'result']
    _STATUS_LABELS = ['Serial Number',
                      'Camera Functionality',
                      'Camera Visual Correctness',
                      'Camera Lens Shading',
                      'Camera Image Sharpness',
                      'ALS Functionality',
                      'Test Result']

    # LED patterns.
    _LED_PREPARE_CAM_TEST = ((leds.LED_NUM, 0.25), (0, 0.25))
    _LED_RUNNING_CAM_TEST = ((leds.LED_NUM, 0.05), (0, 0.05))
    _LED_PREPARE_ALS_TEST = ((leds.LED_NUM|leds.LED_CAP, 0.25),
                             (leds.LED_NUM, 0.25))
    _LED_RUNNING_ALS_TEST = ((leds.LED_NUM|leds.LED_CAP, 0.05),
                             (leds.LED_NUM, 0.05))
    _LED_FINISHED_ALL_TEST = ((leds.LED_NUM|leds.LED_CAP, 0.25),
                              (leds.LED_NUM|leds.LED_CAP, 0.25))

    def advance_state(self):
        if self.type == _TEST_TYPE_FULL:
            self._state = self._state + 1
            # Skip entering SN for full machine test.
            if self._state == self._STATE_ENTERING_SN:
                self._state = self._state + 1
        else:
            if self._state == self._STATE_RESULT_TAB:
                self._state = self._STATE_PREPARE_MACHINE
            else:
                self._state = self._state + 1
        self.switch_widget(self._state_widget[self._state])

    def prepare_test(self):
        self.ref_data = camperf.PrepareTest(self._TEST_CHART_FILE)

    def on_usb_insert(self, dev_path):
        if self._state == self._STATE_WAIT_USB:
            # Initialize common test reference data.
            self.prepare_test()
            # Load config files and reset test results.
            self.dev_path = dev_path
            with MountedMedia(dev_path, 1) as config_dir:
                config_path = os.path.join(config_dir, 'camera.params')
                self.config = self.base_config.Read(config_path)
                self.reset_data()
                self.advance_state()
                factory.log("Config loaded.")

    def on_usb_remove(self, dev_path):
        if self._state != self._STATE_WAIT_USB:
            raise Exception("USB removal is not allowed during test")

    def register_callbacks(self, window):
        def key_press_callback(widget, event):
            if hasattr(self, 'last_widget'):
                if hasattr(self.last_widget, 'key_callback'):
                    return self.last_widget.key_callback(widget, event)
            return False
        window.connect('key-press-event', key_press_callback)
        window.add_events(gtk.gdk.KEY_PRESS_MASK)

    def switch_widget(self, widget_to_display):
        if hasattr(self, 'last_widget'):
            if widget_to_display is not self.last_widget:
                self.last_widget.hide()
                self.test_widget.remove(self.last_widget)
            else:
                return

        self.last_widget = widget_to_display
        self.test_widget.add(widget_to_display)
        self.test_widget.show_all()

    def on_sn_keypress(self, entry, key):
        if key.keyval == gtk.keysyms.Tab:
            entry.set_text(_TEST_SN_NUMBER)
            return True
        return False

    def on_sn_complete(self, serial_number):
        self.serial_number = serial_number
        # TODO(itspeter): display the SN info in the result tab.
        self._update_status('sn', self.check_sn_format(serial_number))
        self.advance_state()

    def check_sn_format(self, sn):
        if re.search(self.config['sn_format'], sn):
            return True
        return False

    def write_to_usb(self, filename, content, content_type=_CONTENT_TXT):
        with MountedMedia(self.dev_path, 1) as mount_dir:
            if content_type == _CONTENT_TXT:
                with open(os.path.join(mount_dir, filename), 'w') as f:
                    f.write(content)
            elif content_type == _CONTENT_IMG:
                cv2.imwrite(os.path.join(mount_dir, filename), content)
        return True

    def _setup_fixture(self):
        '''Initialize the communication with the fixture.'''
        try:
            self.fixture = Fixture(self.config['fixture'])

            # Go with the default(first) lighting intensity.
            self.light_state = 0
            self.fixture.set_light(self.light_state)
            if not self.unit_test:
                self.fixture.assert_success()
        except Exception as e:
            self.fixture = None
            self.log('Failed to initialize the test fixture.\n')
            return False
        self.log('Test fixture successfully initialized.\n')
        return True

    def _capture_low_noise_image(self, cam, n_samples):
        '''Capture a sequence of images and average them to reduce noise.'''
        if n_samples < 1:
            n_samples = 1
        _, img = cam.read()
        img = img.astype(np.float64)
        for t in range(n_samples - 1):
            _, temp_img = cam.read()
            img += temp_img.astype(np.float64)
        img /= n_samples
        return img.round().astype(np.uint8)

    def _test_camera_functionality(self):
        # Initialize the camera with OpenCV.
        cam = cv2.VideoCapture(self._DEVICE_INDEX)
        if not cam.isOpened():
            cam.release()
            self._update_status('cam_stat', False)
            self.log('Failed to initialize the camera. '
                     'Could be bad module, bad connection or '
                     'insufficient USB bandwidth.\n')
            return False

        # Set resolution.
        conf = self.config['cam_stat']
        cam.set(cv.CV_CAP_PROP_FRAME_WIDTH, conf['img_width'])
        cam.set(cv.CV_CAP_PROP_FRAME_HEIGHT, conf['img_height'])
        if (conf['img_width'] != cam.get(cv.CV_CAP_PROP_FRAME_WIDTH) or
            conf['img_height'] != cam.get(cv.CV_CAP_PROP_FRAME_HEIGHT)):
            cam.release()
            self._update_status('cam_stat', False)
            self.log("Can't set the image size. "
                     "Possibly caused by insufficient USB bandwidth.\n")
            return False

        # Try reading an image from the camera.
        success, _ = cam.read()
        if not success:
            cam.release()
            self._update_status('cam_stat', False)
            self.log("Failed to capture an image with the camera.\n")
            return False

        # Let the camera's auto-exposure algorithm adjust to the fixture
        # lighting condition.
        start = time.clock()
        while time.clock() - start < conf['buf_time']:
            _, _ = cam.read()

        # Read the image that we will use.
        n_samples = conf['n_samples']
        img = self._capture_low_noise_image(cam, n_samples)
        self.target = cv2.cvtColor(img, cv.CV_BGR2GRAY)
        self._update_status('cam_stat', True)
        self.log('Successfully captured an image.\n')

        # Use the sample image in the unit-test mode.
        if self.unit_test:
            self.target = cv2.imread(self._TEST_SAMPLE_FILE,
                                     cv.CV_LOAD_IMAGE_GRAYSCALE)
        cam.release()
        return True

    def _test_camera_core(self):
        if not self._test_camera_functionality():
            return

        # Check the captured test pattern image validity.
        success, tar_data = camperf.CheckVisualCorrectness(
            self.target, self.ref_data, **self.config['cam_vc'])

        self._update_status('cam_vc', success)
        if hasattr(tar_data, 'shift'):
            self.log('Image shift percentage: %f\n' % tar_data.shift)
            self.log('Image tilt: %f degrees\n' % tar_data.tilt)
        if not success:
            if hasattr(tar_data, 'sample_corners'):
                self.log('Found corners count: %d\n' %
                         tar_data.sample_corners.shape[0])
            if hasattr(tar_data, 'edges'):
                self.log('Found square edges count: %d\n' %
                         tar_data.edges.shape[0])
            self.log('Visual correctness: %s\n' % tar_data.msg)
            return

        # Check if the lens shading is present.
        success, tar_ls = camperf.CheckLensShading(
            self.target, **self.config['cam_ls'])

        self._update_status('cam_ls', success)
        if tar_ls.check_low_freq:
            self.log('Low-frequency response value: %f\n' %
                                   tar_ls.response)
        if not success:
            self.log('Lens shading: %s\n' % tar_ls.msg)
            return

        # Check the image sharpness.
        success, tar_mtf = camperf.CheckSharpness(
            self.target, tar_data.edges, **self.config['cam_mtf'])

        self._update_status('cam_mtf', success)
        self.log('MTF value: %f\n' % tar_mtf.mtf)
        if hasattr(tar_mtf, 'min_mtf'):
            self.log('Lowest MTF value: %f\n' % tar_mtf.min_mtf)
        if not success:
            self.log('Sharpness: %s\n' % tar_mtf.msg)
        return

    def _test_als_core(self):
        # Initialize the ALS.
        conf = self.config['als']
        self.als = ALS(val_path=conf['val_path'],
                       scale_path=conf['scale_path'])
        if not self.als.detected:
            self._update_status('als_stat', False)
            self.log('Failed to initialize the ALS.\n')
            return

        # Go through all different lighting settings
        # and record ALS values.
        try:
            while True:
                # Get ALS values.
                scale = self.als.get_scale_factor()
                val = self.als.read_mean(samples=5, delay=0)
                self.log('Lighting preset lux value: %d\n',
                         conf['luxs'][self.light_state])
                self.log('ALS value: %d\n' % val)
                self.log('ALS calibration scale: %d\n' % scale)

                # Go to the next lighting preset.
                self.light_state += 1
                self.fixture.set_light(self.light_state)
                if not self.unit_test:
                    self.fixture.assert_success()
                if self.light_state >= len(conf['luxs']):
                    break
                self.fixture.wait_for_light_switch()
        except (FixtureException, serial.serialutil.SerialException) as e:
            self.fixture = None
            self._update_status('als_stat', None)
            self.log("The test fixture was disconnected!\n")
            return
        except:
            self._update_status('als_stat', False)
            self.log('Failed to read values from ALS.\n')
            return
        self._update_status('als_stat', True)
        self.log('Successfully recorded ALS values.\n')
        return

    def test_camera(self, skip_flag):
        if self.type == _TEST_TYPE_FULL:
            self.blinker.Stop()

            if not skip_flag:
                with leds.Blinker(self._LED_RUNNING_CAM_TEST):
                    self._test_camera_core()

            self.blinker = leds.Blinker(self._LED_PREPARE_ALS_TEST)
            self.blinker.Start()
        else:
            if not skip_flag:
                self._test_camera_core()

        self.advance_state()

    def test_als(self, skip_flag):
        if self.type == _TEST_TYPE_FULL:
            self.blinker.Stop()

            if not skip_flag:
                with leds.Blinker(self._LED_RUNNING_ALS_TEST):
                    self._test_als_core()

            self.blinker = leds.Blinker(self._LED_FINISHED_ALL_TEST)
            self.blinker.Start()
        else:
            if not skip_flag:
                self._test_als_core()

        self.generate_final_result()
        self.advance_state()

    def _update_status(self, row_name, result):
        """Updates status in display_dict."""
        result_map = {
            True: ful.PASSED,
            False: ful.FAILED,
            None: ful.UNTESTED
        }
        assert result in result_map, "Unknown result"
        self.display_dict[row_name]['status'] = result_map[result]

    def generate_final_result(self):
        self._result = all(
           ful.PASSED == self.display_dict[var]['status']
           for var in self.status_names[:-1])
        self._update_status('result', self._result)
        self.log("Result in summary:\n%s\n" %
                 pprint.pformat(self.display_dict))

    def save_log(self):
        # Save an image for further analysis in case of the camera
        # performance fail.
        cam_perf_pass = all(ful.PASSED == self.display_dict[var]['status']
                            for var in ['cam_vc', 'cam_ls', 'cam_mtf'])
        if (not cam_perf_pass) and (self.target is not None):
            if not self.write_to_usb(self.serial_number + ".bmp",
                                     self.target, _CONTENT_IMG):
                return False
        return self.write_to_usb(
            self.serial_number + ".txt", self.log_to_file.getvalue())

    def reset_data(self):
        self.target = None
        if self.type == _TEST_TYPE_FULL:
            self.log = logging.info
        else:
            self.log_to_file = StringIO.StringIO()
            self.sn_input_widget.get_entry().set_text('')
            self.log = self.log_to_file.write

        for var in self.status_names:
            self._update_status(var, None)

    def on_result_enter(self):
        if self.type == _TEST_TYPE_FULL:
            self.blinker.Stop()
            gtk.main_quit()
        else:
            # The UI will stop in this screen unless log is saved.
            if self.save_log():
                self.reset_data()
                self.advance_state()
        return False

    def on_close_prepare_machine(self):
        if self.type == _TEST_TYPE_FULL:
            self.blinker = leds.Blinker(self._LED_PREPARE_CAM_TEST)
            self.blinker.Start()
        # Try to setup the fixture if not yet.
        # This happens everytime in the full machine test, when the first time
        # the AB panel test is run and when the fixture is disconnected during
        # the previous test. This step blocks until we can find the fixture
        # successfully.
        if not hasattr(self, 'fixture') or self.fixture is None:
            if not self._setup_fixture():
                return False
        self.advance_state()
        return True

    def make_result_widget(self, on_key_enter):
        widget = gtk.VBox()
        widget.add(ful.make_label(_MESSAGE_RESULT_TAB_FULL
                                  if self.type == _TEST_TYPE_FULL
                                  else _MESSAGE_RESULT_TAB_ABONLY))

        for name, label in zip(self.status_names, self.status_labels):
            td, tw = ful.make_status_row(label, ful.UNTESTED, _LABEL_SIZE)
            self.display_dict[name] = td
            widget.add(tw)
        def key_press_callback(widget, event):
            if event.keyval == gtk.keysyms.Return:
                on_key_enter()

        widget.key_callback = key_press_callback
        return widget

    def run_once(self, test_type=_TEST_TYPE_FULL, unit_test=False):
        '''The entry point of the test.

        Args:
            test_type: Run the full machine test or the AB panel test. The AB
                       panel will be run on a host that is used to test
                       connected AB panels (possibly many), while the full
                       machine test would test only the machine that runs it
                       and then exit.
            unit_test: Run the unit-test mode. The unit-test mode is used to
                       test the test integrity when the test fixture is not
                       available. It should be run on a machine that has a
                       working camera and a working ALS. Please place the
                       camera parameter file under the src directory on an USB
                       stick for use and connect the machine with an
                       USB-to-RS232 converter cable with the designated chipset
                       in the parameter file. The test will replace the
                       captured image with the sample test image and run the
                       camera performance test on it.
        '''
        factory.log('%s run_once' % self.__class__)

        # Initialize variables.
        assert test_type in [_TEST_TYPE_FULL, _TEST_TYPE_AB]
        assert unit_test in [True, False]
        self.type = test_type
        self.unit_test = unit_test
        self.display_dict = {}
        self.base_config = PluggableConfig({})
        self.last_handler = None
        os.chdir(self.srcdir)
        if self.type == _TEST_TYPE_FULL:
            self.status_names = self._STATUS_NAMES[1:]
            self.status_labels = self._STATUS_LABELS[1:]
        else:
            self.status_names = self._STATUS_NAMES
            self.status_labels = self._STATUS_LABELS

        # Set up the UI widgets.
        self.usb_prompt_widget = gtk.VBox()
        self.usb_prompt_widget.add(ful.make_label(_MESSAGE_USB))
        self.prepare_machine_widget = make_prepare_widget(
            (_MESSAGE_PREPARE_MACHINE if self.type == _TEST_TYPE_FULL
             else _MESSAGE_PREPARE_PANEL),
            self.on_close_prepare_machine)
        self.prepare_camera_widget = make_prepare_widget(
                _MESSAGE_PREPARE_CAMERA,
                lambda : self.test_camera(skip_flag=False),
                lambda : self.test_camera(skip_flag=True))
        self.prepare_als_widget = make_prepare_widget(
                _MESSAGE_PREPARE_ALS,
                lambda : self.test_als(skip_flag=False),
                lambda : self.test_als(skip_flag=True))
        self.result_widget = self.make_result_widget(self.on_result_enter)

        self.sn_input_widget = ful.make_input_window(
            prompt='Enter Serial Number (TAB to use testing sample SN):',
            on_validate=self.check_sn_format,
            on_keypress=self.on_sn_keypress,
            on_complete=self.on_sn_complete)

        # Make sure the entry in widget will have focus.
        self.sn_input_widget.connect(
            "show",
            lambda *x : self.sn_input_widget.get_entry().grab_focus())

        # Setup the relation of states and widgets.
        self._state_widget = {
            self._STATE_INITIAL: None,
            self._STATE_WAIT_USB: self.usb_prompt_widget,
            self._STATE_PREPARE_MACHINE: self.prepare_machine_widget,
            self._STATE_ENTERING_SN: self.sn_input_widget,
            self._STATE_PREPARE_CAMERA: self.prepare_camera_widget,
            self._STATE_PREPARE_ALS: self.prepare_als_widget,
            self._STATE_RESULT_TAB: self.result_widget
        }

        # Setup the usb monitor,
        monitor = MediaMonitor()
        monitor.start(on_insert=self.on_usb_insert,
                      on_remove=self.on_usb_remove)

        # Setup the initial display.
        self.test_widget = gtk.VBox()
        self._state = self._STATE_INITIAL
        self.advance_state()
        ful.run_test_widget(
                self.job,
                self.test_widget,
                window_registration_callback=self.register_callbacks)

        if not self._result:
            raise error.TestFail('Camera/ALS test failed by user indication\n' +
                                 '品管人員懷疑故障，請檢修')

        factory.log('%s run_once finished' % self.__class__)
