# Copyright 2016 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.

"""A factory test to test the function of display.

The test will display images on the display.
It will extract image files from factory/misc/display_images.tar.gz by default.
User can add new xx.tar.gz in the private overlay.
The display order is based on the sorted file name.

Two directories, dut/ and station/, are required in the image archive xx.tar.gz.
For each image to be tested, two images with same file name are required in each
directory, but we can use different extension name depending on the file format.
The image under dut/ is for displaying on DUT. The image under station/ is for
providing information to operators.
e.g.
dut/abc.ppm and station/abc.bmp
"""

import glob
import logging
import os

import factory_common  # pylint: disable=unused-import
from cros.factory.device import device_utils
from cros.factory.test.i18n import _
from cros.factory.test.i18n import arg_utils as i18n_arg_utils
from cros.factory.test import test_case
from cros.factory.test import test_ui
from cros.factory.utils.arg_utils import Arg
from cros.factory.utils import file_utils
from cros.factory.utils import process_utils

_IMAGE_ROOT = '/usr/local/factory/misc/'
_DEFAULT_IMAGE_FILE = 'display_images.tar.gz'
_IMAGE_DIR = 'images'
_STATION_IMAGE_DIR = 'station'
_DUT_IMAGE_DIR = 'dut'


class DisplayImageTest(test_case.TestCase):
  """Tests the function of display by displaying images.

  Properties:
    _extract_dir: temp directory for keeping image files on the station.
    _station_image_urls: list of image paths for displaying on Station.
    _dut_temp_dir: temp directory for keeping image files on DUT.
    _image_index: index of the image to be displayed.
    _uploaded_index: index of the latest uploaded image.
    _total_images: number of total images.
    _can_pass: check if operator checks all images.
  """
  ARGS = [
      i18n_arg_utils.I18nArg(
          'title', 'Label Title of the test', default=_('Display Test')),
      Arg('compressed_image_file', str, 'Compressed image file name.',
          default=_DEFAULT_IMAGE_FILE)
  ]

  def setUp(self):
    """Initializes frontend presentation and properties."""
    self._dut = device_utils.CreateDUTInterface()

    self.ui.SetHTML(self.args.title, id='display-title')
    self._dut_temp_dir = self._dut.temp.mktemp(True, '', 'display')
    self._image_index = -1
    self._uploaded_index = -1
    self._can_pass = False

    self._extract_dir = os.path.join(self.ui.GetStaticDirectoryPath(),
                                     _IMAGE_DIR)
    file_utils.ExtractFile(
        os.path.join(_IMAGE_ROOT, self.args.compressed_image_file),
        self._extract_dir)

    image_paths = sorted(
        glob.glob(os.path.join(self._extract_dir, _DUT_IMAGE_DIR, '*')))
    self._dut_image_paths = [
        self._dut.path.join(self._dut_temp_dir, os.path.basename(x))
        for x in image_paths
    ]

    station_paths = sorted(
        glob.glob(os.path.join(self._extract_dir, _STATION_IMAGE_DIR, '*')))
    self._station_image_urls = [
        os.path.join(_IMAGE_DIR, _STATION_IMAGE_DIR, os.path.basename(x))
        for x in station_paths
    ]

    self.assertEqual(
        len(image_paths),
        len(station_paths),
        'There should be same number of images in dut and station folders.')

    # Because uploading images cost a lot of time, use another thread to do it.
    # Operator can test uploaded images in parallel.
    process_utils.StartDaemonThread(
        target=self.UploadImages, args=(station_paths, ))

    images = ''.join('<img src="%s" class="image-thumb">' % path
                     for path in self._station_image_urls)
    self.ui.SetHTML(images, id='display-table')

  def tearDown(self):
    self._dut.display.StopDisplayImage()
    process_utils.Spawn(['rm', '-rf', self._extract_dir],
                        check_call=True, log=True)
    self._dut.Call(['rm', '-rf', self._dut_temp_dir])

  def runTest(self):
    """Sets the callback function of keys and run the test."""
    while True:
      pressed_key = self.ui.WaitKeysOnce([test_ui.SPACE_KEY, test_ui.ENTER_KEY])
      if pressed_key == test_ui.SPACE_KEY:
        self.OnSpacePressed()
      elif pressed_key == test_ui.ENTER_KEY:
        if self._can_pass:
          break

  def UploadImages(self, image_paths):
    """Upload images to DUT."""
    for i in xrange(len(image_paths)):
      # path in the station
      path = image_paths[i]
      dut_path = self._dut_image_paths[i]
      name = os.path.basename(path)
      self.ui.SetHTML(
          _('({index}/{total}) Uploading images {name}',
            index=i + 1,
            total=len(image_paths),
            name=name),
          id='upload')
      self._dut.link.Push(path, dut_path)
      self._uploaded_index = i
    self.ui.SetHTML(_('All images uploaded.'), id='upload')

  def OnSpacePressed(self):
    """Display next image."""
    display_index = (self._image_index + 1) % len(self._station_image_urls)
    # Don't do display if the image is not uploaded.
    if display_index > self._uploaded_index:
      return

    # show the image on the chromebook to let operator know what will be shown
    # on the DUT.
    path = self._station_image_urls[display_index]
    tag = '%d: <img src="%s" class="image-info">' % (display_index, path)
    self.ui.SetHTML(tag, id='display-image-info')
    # Display image on DUT.
    dut_path = self._dut_image_paths[display_index]
    logging.info('Display image index %d, image %s, dut path %s',
                 display_index, path, dut_path)
    self._dut.display.StopDisplayImage()
    self._dut.display.DisplayImage(dut_path)
    self._image_index = display_index

    if display_index == len(self._station_image_urls) - 1:
      self._can_pass = True
