# Copyright (C) 2010 Google Inc. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
#     * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#     * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
#     * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

from six.moves import cPickle

from blinkpy.web_tests.controllers import repaint_overlay
from blinkpy.web_tests.models.typ_types import ResultType
from blinkpy.common.html_diff import html_diff
from blinkpy.common.unified_diff import unified_diff

# TODO(rmhasan) Create a unit test for each Failure type and make
# sure each artifact is written to the correct path

# FIXME: old-run-webkit-tests shows the diff percentage as the text
#   contents of the "diff" link.
# FIXME: old-run-webkit-tests include a link to the test file.
_image_diff_html_template = """<!DOCTYPE HTML>
<html>
<head>
<title>%(title)s</title>
<style>.label{font-weight:bold}</style>
</head>
<body>
Difference between images: <a href="%(diff_filename)s">diff</a><br>
<div class=imageText></div>
<div class=imageContainer data-prefix="%(prefix)s">Loading...</div>
<script>
(function() {
var preloadedImageCount = 0;
function preloadComplete() {
++preloadedImageCount;
if (preloadedImageCount < 2)
    return;
toggleImages();
setInterval(toggleImages, 2000)
}

function preloadImage(url) {
image = new Image();
image.addEventListener('load', preloadComplete);
image.src = url;
return image;
}

function toggleImages() {
if (text.textContent == 'Expected Image') {
    text.textContent = 'Actual Image';
    container.replaceChild(actualImage, container.firstChild);
} else {
    text.textContent = 'Expected Image';
    container.replaceChild(expectedImage, container.firstChild);
}
}

var text = document.querySelector('.imageText');
var container = document.querySelector('.imageContainer');
var actualImage = preloadImage(container.getAttribute('data-prefix') + '-actual.png');
var expectedImage = preloadImage(container.getAttribute('data-prefix') + '-expected.png');
})();
</script>
</body>
</html>"""

# Filename pieces when writing failures to the test results directory.
FILENAME_SUFFIX_ACTUAL = "-actual"
FILENAME_SUFFIX_EXPECTED = "-expected"
FILENAME_SUFFIX_CMD = "-command"
FILENAME_SUFFIX_DIFF = "-diff"
FILENAME_SUFFIX_DIFFS = "-diffs"
FILENAME_SUFFIX_STDERR = "-stderr"
FILENAME_SUFFIX_CRASH_LOG = "-crash-log"
FILENAME_SUFFIX_SAMPLE = "-sample"
FILENAME_SUFFIX_LEAK_LOG = "-leak-log"
FILENAME_SUFFIX_HTML_DIFF = "-pretty-diff"
FILENAME_SUFFIX_OVERLAY = "-overlay"

_ext_to_file_type = {'.txt': 'text', '.png': 'image', '.wav': 'audio'}


def has_failure_type(failure_type, failure_list):
    return any(isinstance(failure, failure_type) for failure in failure_list)


class AbstractTestResultType(object):
    port = None
    test_name = None
    filesystem = None
    result_directory = None
    result = ResultType.Pass

    def __init__(self, actual_driver_output, expected_driver_output):
        self.actual_driver_output = actual_driver_output
        self.expected_driver_output = expected_driver_output
        self.has_stderr = False
        self.has_repaint_overlay = False
        self.is_reftest = False
        if actual_driver_output:
            self.has_stderr = actual_driver_output.has_stderr()
        if expected_driver_output:
            self.has_stderr |= expected_driver_output.has_stderr()

    def _write_to_artifacts(self, typ_artifacts, artifact_name, path, content,
                            force_overwrite):
        typ_artifacts.CreateArtifact(
            artifact_name, path, content, force_overwrite=force_overwrite)

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        typ_artifacts_dir = self.filesystem.join(
            self.result_directory, typ_artifacts.ArtifactsSubDirectory())
        if self.actual_driver_output.command:
            artifact_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_CMD, '.txt')
            artifacts_abspath = self.filesystem.join(typ_artifacts_dir,
                                                     artifact_filename)
            if (force_overwrite or self.result != ResultType.Pass
                    or not self.filesystem.exists(artifacts_abspath)):
                self._write_to_artifacts(typ_artifacts,
                                         'command',
                                         artifact_filename,
                                         self.actual_driver_output.command,
                                         force_overwrite=True)

        if self.actual_driver_output.error:
            artifact_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_STDERR, '.txt')
            artifacts_abspath = self.filesystem.join(typ_artifacts_dir,
                                                     artifact_filename)
            # If a test has multiple stderr results, keep that of the last
            # failure, which is useful for debugging flaky tests with
            # --iterations=n or --repeat-each=n.
            if (force_overwrite or self.result != ResultType.Pass
                    or not self.filesystem.exists(artifacts_abspath)):
                self._write_to_artifacts(
                    typ_artifacts,
                    'stderr',
                    artifact_filename,
                    self.actual_driver_output.error,
                    force_overwrite=True)

    @staticmethod
    def loads(s):
        """Creates a AbstractTestResultType object from the specified string."""
        return cPickle.loads(s)

    def message(self):
        """Returns a string describing the failure in more detail."""
        raise NotImplementedError

    def __eq__(self, other):
        return self.__class__.__name__ == other.__class__.__name__

    def __ne__(self, other):
        return self.__class__.__name__ != other.__class__.__name__

    def __hash__(self):
        return hash(self.__class__.__name__)

    def dumps(self):
        """Returns the string/JSON representation of a AbstractTestResultType."""
        return cPickle.dumps(self)

    def driver_needs_restart(self):
        """Returns True if we should kill the driver before the next test."""
        return False

    def message(self):
        raise NotImplementedError

    def text_mismatch_category(self):
        raise NotImplementedError


class PassWithStderr(AbstractTestResultType):
    def __init__(self, driver_output):
        # TODO (rmhasan): Should we write out the reference driver standard
        # error
        super(PassWithStderr, self).__init__(driver_output, None)

    def message(self):
        return 'test passed but has standard error output'


class TestFailure(AbstractTestResultType):
    result = ResultType.Failure


class FailureTimeout(AbstractTestResultType):
    result = ResultType.Timeout

    def __init__(self, actual_driver_output, is_reftest=False):
        super(FailureTimeout, self).__init__(actual_driver_output, None)
        self.is_reftest = is_reftest

    def message(self):
        return 'test timed out'

    def driver_needs_restart(self):
        return True


class FailureCrash(AbstractTestResultType):
    result = ResultType.Crash

    def __init__(self,
                 actual_driver_output,
                 is_reftest=False,
                 process_name='content_shell',
                 pid=None,
                 has_log=False):
        super(FailureCrash, self).__init__(actual_driver_output, None)
        self.process_name = process_name
        self.pid = pid
        self.is_reftest = is_reftest
        self.has_log = has_log
        self.crash_log = self.actual_driver_output.crash_log

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        super(FailureCrash, self).create_artifacts(typ_artifacts,
                                                   force_overwrite)
        if self.crash_log:
            artifact_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_CRASH_LOG, '.txt')
            self._write_to_artifacts(
                typ_artifacts, 'crash_log', artifact_filename,
                self.crash_log.encode('utf8', 'replace'), force_overwrite)

    def message(self):
        if self.pid:
            return '%s crashed [pid=%d]' % (self.process_name, self.pid)
        return self.process_name + ' crashed'

    def driver_needs_restart(self):
        return True


class FailureLeak(TestFailure):
    def __init__(self, actual_driver_output, is_reftest=False):
        super(FailureLeak, self).__init__(actual_driver_output, None)
        self.is_reftest = is_reftest

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        super(FailureLeak, self).create_artifacts(typ_artifacts,
                                                  force_overwrite)
        artifact_filename = self.port.output_filename(
            self.test_name, FILENAME_SUFFIX_LEAK_LOG, '.txt')
        self.log = self.actual_driver_output.leak_log
        self._write_to_artifacts(typ_artifacts, 'leak_log', artifact_filename,
                                 self.log, force_overwrite)

    def message(self):
        return 'leak detected: %s' % (self.log)


class ActualAndBaselineArtifacts(TestFailure):
    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        super(ActualAndBaselineArtifacts, self).create_artifacts(
            typ_artifacts, force_overwrite)
        self.actual_artifact_filename = self.port.output_filename(
            self.test_name, FILENAME_SUFFIX_ACTUAL, self.file_ext)
        self.expected_artifact_filename = self.port.output_filename(
            self.test_name, FILENAME_SUFFIX_EXPECTED, self.file_ext)
        attr = _ext_to_file_type[self.file_ext]
        if getattr(self.actual_driver_output, attr):
            self._write_to_artifacts(typ_artifacts, 'actual_%s' % attr,
                                     self.actual_artifact_filename,
                                     getattr(self.actual_driver_output,
                                             attr), force_overwrite)
        if getattr(self.expected_driver_output, attr):
            self._write_to_artifacts(
                typ_artifacts, 'expected_%s' % attr,
                self.expected_artifact_filename,
                getattr(self.expected_driver_output, attr), force_overwrite)

    def message(self):
        raise NotImplementedError


class FailureText(ActualAndBaselineArtifacts):
    def __init__(self, actual_driver_output, expected_driver_output):
        super(FailureText, self).__init__(actual_driver_output,
                                          expected_driver_output)
        self.has_repaint_overlay = (
            repaint_overlay.result_contains_repaint_rects(
                actual_driver_output.text)
            or repaint_overlay.result_contains_repaint_rects(
                expected_driver_output.text))
        self.file_ext = '.txt'

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        # TODO (rmhasan): See if you can can only output diff files for
        # non empty text.
        super(FailureText, self).create_artifacts(typ_artifacts,
                                                  force_overwrite)
        expected_text = self.expected_driver_output.text or ''
        actual_text = self.actual_driver_output.text or ''
        artifacts_abs_path = self.filesystem.join(
            self.result_directory, typ_artifacts.ArtifactsSubDirectory())
        diff_content = unified_diff(
            expected_text, actual_text,
            self.filesystem.join(artifacts_abs_path,
                                 self.expected_artifact_filename),
            self.filesystem.join(artifacts_abs_path,
                                 self.actual_artifact_filename))
        diff_filename = self.port.output_filename(self.test_name,
                                                  FILENAME_SUFFIX_DIFF, '.txt')
        html_diff_content = html_diff(expected_text, actual_text)
        html_diff_filename = self.port.output_filename(
            self.test_name, FILENAME_SUFFIX_HTML_DIFF, '.html')
        self._write_to_artifacts(typ_artifacts, 'text_diff', diff_filename,
                                 diff_content, force_overwrite)
        self._write_to_artifacts(typ_artifacts, 'pretty_text_diff',
                                 html_diff_filename, html_diff_content,
                                 force_overwrite)

    def message(self):
        raise NotImplementedError

    def text_mismatch_category(self):
        raise NotImplementedError


class FailureMissingResult(FailureText):
    def message(self):
        return '-expected.txt was missing'


class FailureTextNotGenerated(FailureText):
    def message(self):
        return 'test did not generate text results'


class FailureTextMismatch(FailureText):
    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        super(FailureTextMismatch, self).create_artifacts(
            typ_artifacts, force_overwrite)
        html = repaint_overlay.generate_repaint_overlay_html(
            self.test_name, self.actual_driver_output.text,
            self.expected_driver_output.text)
        if html:
            overlay_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_OVERLAY, '.html')
            self._write_to_artifacts(typ_artifacts, 'overlay',
                                     overlay_filename, html, force_overwrite)

    def message(self):
        return 'text diff'

    def text_mismatch_category(self):
        return 'general text mismatch'


class FailureTestHarnessAssertion(FailureText):
    def message(self):
        return 'asserts failed'


class FailureSpacesAndTabsTextMismatch(FailureTextMismatch):
    def message(self):
        return 'text diff by spaces and tabs only'

    def text_mismatch_category(self):
        return 'spaces and tabs only'


class FailureLineBreaksTextMismatch(FailureTextMismatch):
    def message(self):
        return 'text diff by newlines only'

    def text_mismatch_category(self):
        return 'newlines only'


class FailureSpaceTabLineBreakTextMismatch(FailureTextMismatch):
    def message(self):
        return 'text diff by spaces, tabs and newlines only'

    def text_mismatch_category(self):
        return 'spaces, tabs and newlines only'


class FailureImage(ActualAndBaselineArtifacts):
    def __init__(self, actual_driver_output, expected_driver_output):
        super(FailureImage, self).__init__(actual_driver_output,
                                           expected_driver_output)
        self.file_ext = '.png'

    def message(self):
        raise NotImplementedError


class FailureImageHashNotGenerated(FailureImage):
    def message(self):
        return 'test did not generate image results'


class FailureMissingImageHash(FailureImage):
    def message(self):
        return '-expected.png was missing an embedded checksum'


class FailureMissingImage(FailureImage):
    def message(self):
        return '-expected.png was missing'


class FailureImageHashMismatch(FailureImage):
    def message(self):
        return 'image diff'

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        # Need this if statement in case the image diff process fails
        if self.actual_driver_output.image_diff:
            diff_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_DIFF, '.png')
            diff = self.actual_driver_output.image_diff
            self._write_to_artifacts(typ_artifacts, 'image_diff',
                                     diff_filename, diff, force_overwrite)
            diffs_html_filename = self.port.output_filename(
                self.test_name, FILENAME_SUFFIX_DIFFS, '.html')
            diffs_html = _image_diff_html_template % {
                'title': self.test_name,
                'diff_filename': diff_filename,
                'prefix': self.port.output_filename(self.test_name, '', '')
            }
            self._write_to_artifacts(typ_artifacts, 'pretty_image_diff',
                                     diffs_html_filename, diffs_html,
                                     force_overwrite)

        super(FailureImageHashMismatch, self).create_artifacts(
            typ_artifacts, force_overwrite)


class FailureReftestMixin(object):
    # This mixin will be used by reftest failure types to create a reference
    # file artifact along with image mismatch artifacts, actual image output,
    # reference driver output, and standard error output. The actual reftest
    # failure types used in single_test_runner.py each have an inheritance list.
    # The order of this list decides the call order of overridden methods like the
    # constructor and create_artifacts. For example, FailureReftestMismatch
    # has FailureReftestMixin followed by FailureImageHashMismatch. So when
    # create_artifacts is called on that class, FailureReftestMixin's create_artifacts
    # will be called first and then when that method calls the super class's
    # create_artifacts, it will call FailureImageHashMismatch's create_artifacts.

    def __init__(self,
                 actual_driver_output,
                 expected_driver_output,
                 reference_filename=None):
        super(FailureReftestMixin, self).__init__(actual_driver_output,
                                                  expected_driver_output)
        self.reference_filename = reference_filename
        self.reference_file_type = 'reference_file_mismatch'

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        super(FailureReftestMixin, self).create_artifacts(
            typ_artifacts, force_overwrite)
        sub_dir = typ_artifacts.ArtifactsSubDirectory()
        artifact_filename = self.filesystem.join(
            sub_dir, self.filesystem.dirname(self.test_name),
            self.filesystem.basename(self.reference_filename))
        artifact_abspath = self.filesystem.join(self.result_directory,
                                                artifact_filename)
        # a reference test may include a page that does not exist in the
        # web test directory, like about:blank pages
        if (not self.filesystem.exists(artifact_abspath)
                and self.filesystem.exists(self.reference_filename)):
            self.filesystem.maybe_make_directory(
                self.filesystem.dirname(artifact_abspath))
            self.filesystem.copyfile(self.reference_filename, artifact_abspath)
        typ_artifacts.AddArtifact(
            self.reference_file_type,
            artifact_filename,
            raise_exception_for_duplicates=False)

    def message(self):
        raise NotImplementedError


class FailureReftestMismatch(FailureReftestMixin, FailureImageHashMismatch):
    def message(self):
        return 'reference mismatch'


class FailureReftestMismatchDidNotOccur(FailureReftestMixin, FailureImage):
    def __init__(self,
                 actual_driver_output,
                 expected_driver_output,
                 reference_filename=None):
        super(FailureReftestMismatchDidNotOccur, self).__init__(
            actual_driver_output, expected_driver_output, reference_filename)
        self.reference_file_type = 'reference_file_match'

    def message(self):
        return "reference mismatch didn't happen"


class FailureReftestNoImageGenerated(FailureReftestMixin, FailureImage):
    def message(self):
        return "reference test didn't generate pixel results"


class FailureReftestNoReferenceImageGenerated(FailureReftestMixin,
                                              FailureImage):
    def message(self):
        return "-expected.html didn't generate pixel results"


class FailureAudio(ActualAndBaselineArtifacts):
    def __init__(self, actual_driver_output, expected_driver_output):
        super(FailureAudio, self).__init__(actual_driver_output,
                                           expected_driver_output)
        self.file_ext = '.wav'

    def message(self):
        raise NotImplementedError


class FailureMissingAudio(FailureAudio):
    def message(self):
        return 'expected audio result was missing'


class FailureAudioMismatch(FailureAudio):
    def message(self):
        return 'audio mismatch'


class FailureAudioNotGenerated(FailureAudio):
    def message(self):
        return 'audio result not generated'


class FailureEarlyExit(AbstractTestResultType):
    result = ResultType.Skip

    def __init__(self, actual_driver_output=None, expected_driver_output=None):
        super(FailureEarlyExit, self).__init__(actual_driver_output,
                                               expected_driver_output)

    def create_artifacts(self, typ_artifacts, force_overwrite=False):
        pass

    def message(self):
        return 'skipped due to early exit'


# Convenient collection of all failure classes for anything that might
# need to enumerate over them all.
ALL_FAILURE_CLASSES = (FailureTimeout, FailureCrash, FailureMissingResult,
                       FailureTestHarnessAssertion, FailureTextMismatch,
                       FailureSpacesAndTabsTextMismatch,
                       FailureLineBreaksTextMismatch,
                       FailureSpaceTabLineBreakTextMismatch,
                       FailureMissingImageHash, FailureMissingImage,
                       FailureImageHashMismatch, FailureReftestMismatch,
                       FailureReftestMismatchDidNotOccur,
                       FailureReftestNoImageGenerated,
                       FailureReftestNoReferenceImageGenerated,
                       FailureMissingAudio, FailureAudioMismatch,
                       FailureEarlyExit, FailureImageHashNotGenerated,
                       FailureTextNotGenerated, FailureAudioNotGenerated)
