#!/usr/bin/env python
# Copyright 2015 The PDFium 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 distutils.spawn
import itertools
import os
import shutil
import sys

# pylint: disable=relative-import
import common


class PathMode:
  """PathMode indicates the available expected results' paths.

  Attributes:
    DEFAULT:   Used for default expected paths in the format of
               'NAME_expected(_OSNAME)?.pdf.#.png'. For a test, this path always
               exists.
    SKIA:      Used when Skia or SkiaPaths is enabled, for paths in the format
               of 'NAME_expected_skia(_OSNAME)?.pdf.#.png'.
               Such paths only exist when the expected results of Skia or
               SkiaPaths are different from those of AGG.
    SKIAPATHS: Used when SkiaPaths is enabled, for path in the format of
               'NAME_expected_skiapaths(_OSNAME)?.pdf.#.png'.
               Such paths only exist when the expected results from using AGG,
               Skia and SkiaPaths are all different from each other.

  Always check PathMode in an incrementing order as the modes are listed in
  order of its matching paths' precedence.
  """

  DEFAULT = 0
  SKIA = 1
  SKIAPATHS = 2


class NotFoundError(Exception):
  """Raised when file doesn't exist"""
  pass


class PNGDiffer():

  def __init__(self, finder, features, reverse_byte_order):
    self.pdfium_diff_path = finder.ExecutablePath('pdfium_diff')
    self.os_name = finder.os_name
    self.reverse_byte_order = reverse_byte_order
    if 'SKIAPATHS' in features:
      self.max_path_mode = PathMode.SKIAPATHS
    elif 'SKIA' in features:
      self.max_path_mode = PathMode.SKIA
    else:
      self.max_path_mode = PathMode.DEFAULT

  def CheckMissingTools(self, regenerate_expected):
    if (regenerate_expected and self.os_name == 'linux' and
        not distutils.spawn.find_executable('optipng')):
      return 'Please install "optipng" to regenerate expected images.'
    return None

  def GetActualFiles(self, input_filename, source_dir, working_dir):
    actual_paths = []
    path_templates = PathTemplates(input_filename, source_dir, working_dir,
                                   self.os_name, self.max_path_mode)

    for page in itertools.count():
      actual_path = path_templates.GetActualPath(page)
      expected_paths = path_templates.GetExpectedPaths(page)
      if any(itertools.imap(os.path.exists, expected_paths)):
        actual_paths.append(actual_path)
      else:
        break
    return actual_paths

  def _RunImageDiffCommand(self, expected_path, actual_path):
    if not os.path.exists(expected_path):
      return NotFoundError('%s does not exist.' % expected_path)

    cmd = [self.pdfium_diff_path]
    if self.reverse_byte_order:
      cmd.append('--reverse-byte-order')
    cmd.extend([expected_path, actual_path])
    return common.RunCommand(cmd)

  def HasDifferences(self, input_filename, source_dir, working_dir):
    path_templates = PathTemplates(input_filename, source_dir, working_dir,
                                   self.os_name, self.max_path_mode)
    for page in itertools.count():
      actual_path = path_templates.GetActualPath(page)
      expected_paths = path_templates.GetExpectedPaths(page)
      if not any(itertools.imap(os.path.exists, expected_paths)):
        if page == 0:
          print "WARNING: no expected results files for " + input_filename
        if os.path.exists(actual_path):
          print('FAILURE: Missing expected result for 0-based page %d of %s' %
                (page, input_filename))
          return True
        break
      print "Checking " + actual_path
      sys.stdout.flush()

      error = None
      for path in expected_paths:
        new_error = self._RunImageDiffCommand(path, actual_path)
        # Update error code. No need to overwrite the previous error code if
        # |path| doesn't exist.
        if not isinstance(new_error, NotFoundError):
          error = new_error
        # Found a match and proceed to next page
        if not error:
          break

      if error:
        print "FAILURE: " + input_filename + "; " + str(error)
        return True

    return False

  # TODO(crbug.com/pdfium/1508): Add support to automatically generate
  # Skia/SkiaPaths specific expected results.
  def Regenerate(self, input_filename, source_dir, working_dir, platform_only):
    path_templates = PathTemplates(input_filename, source_dir, working_dir,
                                   self.os_name, self.max_path_mode)

    for page in itertools.count():
      # Loop through the generated page images. Stop when there is a page
      # missing a png, which means the document ended.
      actual_path = path_templates.GetActualPath(page)
      if not os.path.isfile(actual_path):
        break

      platform_expected_path = path_templates.GetExpectedPathByPathMode(
          page, PathMode.DEFAULT, self.os_name)

      # If there is a platform expected png, we will overwrite it. Otherwise,
      # overwrite the generic png in "all" mode, or do nothing in "platform"
      # mode.
      if os.path.exists(platform_expected_path):
        expected_path = platform_expected_path
      elif not platform_only:
        expected_path = path_templates.GetExpectedPathByPathMode(
            page, PathMode.DEFAULT)
      else:
        continue

      shutil.copyfile(actual_path, expected_path)
      common.RunCommand(['optipng', expected_path])


ACTUAL_TEMPLATE = '.pdf.%d.png'

class PathTemplates(object):

  def __init__(self, input_filename, source_dir, working_dir, os_name,
               max_path_mode):
    assert PathMode.DEFAULT <= max_path_mode <= PathMode.SKIAPATHS, (
        'Unexpected Maximum PathMode: %d.' % max_path_mode)

    input_root, _ = os.path.splitext(input_filename)
    self.actual_path_template = os.path.join(working_dir,
                                             input_root + ACTUAL_TEMPLATE)
    self.source_dir = source_dir
    self.input_root = input_root
    self.max_path_mode = max_path_mode
    self.os_name = os_name

    # Pre-create the available templates depending on |max_path_mode|.
    self.expected_templates = []
    for mode in range(PathMode.DEFAULT, max_path_mode + 1):
      self.expected_templates.extend([
          self._GetExpectedTemplateByPathMode(mode),
          self._GetExpectedTemplateByPathMode(mode, os_name),
      ])

  def GetActualPath(self, page):
    return self.actual_path_template % page

  def _GetExpectedTemplateByPathMode(self, mode, os_name=None):
    expected_str = '_expected'
    if mode == PathMode.DEFAULT:
      pass
    elif mode == PathMode.SKIA:
      expected_str += '_skia'
    elif mode == PathMode.SKIAPATHS:
      expected_str += '_skiapaths'
    else:
      assert False, 'Unexpected PathMode: %d.' % mode

    if os_name:
      expected_str += '_' + self.os_name
    return os.path.join(self.source_dir,
                        self.input_root + expected_str + ACTUAL_TEMPLATE)

  def GetExpectedPathByPathMode(self, page, mode, os_name=None):
    return self._GetExpectedTemplateByPathMode(mode, os_name) % page

  def GetExpectedPaths(self, page):
    return [template % page for template in self.expected_templates]
