# Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above
#    copyright notice, this list of conditions and the following
#    disclaimer.
# 2. 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.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "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 HOLDER 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.

import os
import re
import unittest

from webkitpy.common.host import Host
from webkitpy.common.system.outputcapture import OutputCapture
from webkitpy.common.webkit_finder import WebKitFinder
from webkitpy.common.unicode_compatibility import unicode
from webkitpy.thirdparty.BeautifulSoup import BeautifulSoup
from webkitpy.w3c.test_converter import _W3CTestConverter

DUMMY_FILENAME = 'dummy.html'
DUMMY_PATH = 'dummy/testharness/path'


class W3CTestConverterTest(unittest.TestCase):

    # FIXME: When we move to using a MockHost, this method should be removed, since
    #        then we can just pass in a dummy dir path
    def fake_dir_path(self, dirname):
        filesystem = Host().filesystem
        webkit_root = WebKitFinder(filesystem).webkit_base()
        return filesystem.abspath(filesystem.join(webkit_root, "LayoutTests", "css", dirname))

    def test_read_prefixed_property_list(self):
        """ Tests that the current list of properties requiring the -webkit- prefix load correctly """

        # FIXME: We should be passing in a MockHost here ...
        converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)
        prop_list = converter.prefixed_properties
        self.assertTrue(prop_list, 'No prefixed properties found')
        property_values_list = converter.prefixed_property_values
        self.assertTrue(property_values_list, 'No prefixed property values found')

    def test_convert_for_webkit_nothing_to_convert(self):
        """ Tests convert_for_webkit() using a basic test that has nothing to convert """

        test_html = """<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Test: DESCRIPTION OF TEST</title>
<link rel="author" title="NAME_OF_AUTHOR"
href="mailto:EMAIL OR http://CONTACT_PAGE"/>
<link rel="help" href="RELEVANT_SPEC_SECTION"/>
<meta name="assert" content="TEST ASSERTION"/>
<style type="text/css"><![CDATA[
CSS FOR TEST
]]></style>
</head>
<body>
CONTENT OF TEST
</body>
</html>
"""
        converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)

        oc = OutputCapture()
        oc.capture_output()
        try:
            converter.feed(test_html)
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_no_conversion_happened(converted, test_html)

    def test_convert_for_webkit_harness_only(self):
        """ Tests convert_for_webkit() using a basic JS test that uses testharness.js only and has no prefixed properties """

        test_html = """<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
</head>
"""
        fake_dir_path = self.fake_dir_path("harnessonly")
        converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
        converter.feed(test_html)
        converter.close()
        converted = converter.output()

        self.verify_conversion_happened(converted)
        self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
        self.verify_prefixed_properties(converted, [])
        self.verify_prefixed_property_values(converted, [])

    def test_convert_for_webkit_properties_only(self):
        """ Tests convert_for_webkit() using a test that has 2 prefixed properties: 1 in a style block + 1 inline style """

        test_html = """<html>
<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<style type="text/css">

#block1 { @test0@: @propvalue0@; }

</style>
</head>
<body>
<div id="elem1" style="@test1@: @propvalue1@;"></div>
</body>
</html>
"""
        fake_dir_path = self.fake_dir_path('harnessandprops')
        converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)
        test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 1, test_html)

        oc = OutputCapture()
        oc.capture_output()
        try:
            converter.feed(test_content[2])
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_conversion_happened(converted)
        self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
        self.verify_prefixed_properties(converted, test_content[0])
        self.verify_prefixed_property_values(converted, test_content[1])

    def test_convert_for_webkit_harness_and_properties(self):
        """ Tests convert_for_webkit() using a basic JS test that uses testharness.js and testharness.css and has 4 prefixed properties: 3 in a style block + 1 inline style """

        test_html = """<html>
<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<style type="text/css">

#block1 { @test0@: @propvalue0@; }
#block2 { @test1@: @propvalue1@; }
#block3 { @test2@: @propvalue2@; }

</style>
</head>
<body>
<div id="elem1" style="@test3@: @propvalue3@;"></div>
</body>
</html>
"""
        fake_dir_path = self.fake_dir_path('harnessandprops')
        converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)

        oc = OutputCapture()
        oc.capture_output()
        try:
            test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 2, test_html)
            converter.feed(test_content[2])
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_conversion_happened(converted)
        self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 1, 1)
        self.verify_prefixed_properties(converted, test_content[0])
        self.verify_prefixed_property_values(converted, test_content[1])

    def test_convert_test_harness_paths(self):
        """ Tests convert_testharness_paths() with a test that uses all three testharness files """

        test_html = """<head>
<link href="/resources/testharness.css" rel="stylesheet" type="text/css">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
</head>
"""
        fake_dir_path = self.fake_dir_path('testharnesspaths')
        converter = _W3CTestConverter(fake_dir_path, DUMMY_FILENAME, None)

        oc = OutputCapture()
        oc.capture_output()
        try:
            converter.feed(test_html)
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_conversion_happened(converted)
        self.verify_test_harness_paths(converter, converted[2], fake_dir_path, 2, 1)

    def test_convert_prefixed_properties(self):
        """ Tests convert_prefixed_properties() file that has 20 properties requiring the -webkit- prefix:
        10 in one style block + 5 in another style
        block + 5 inline styles, including one with multiple prefixed properties.
        The properties in the test content are in all sorts of wack formatting.
        """

        test_html = """<html>
<style type="text/css"><![CDATA[

.block1 {
    width: 300px;
    height: 300px
}

.block2 {
    @test0@: @propvalue0@;
}

.block3{@test1@: @propvalue1@;}

.block4 { @test2@:@propvalue2@; }

.block5{ @test3@ :@propvalue3@; }

#block6 {    @test4@   :   @propvalue4@   ;  }

#block7
{
    @test5@: @propvalue5@;
}

#block8 { @test6@: @propvalue6@ }

#block9:pseudo
{

    @test7@: @propvalue7@;
    @test8@:  propvalue propvalue propvalue;;
    propname:
@propvalue8@;
}

]]></style>
</head>
<body>
    <div id="elem1" style="@test9@: @propvalue9@;"></div>
    <div id="elem2" style="propname: propvalue; @test10@ : @propvalue10@; propname:propvalue;"></div>
    <div id="elem2" style="@test11@: @propvalue11@; @test12@ : @propvalue12@; @test13@   :   @propvalue13@   ;"></div>
    <div id="elem3" style="@test14@:@propvalue14@"></div>
</body>
<style type="text/css"><![CDATA[

.block10{ @test15@: @propvalue15@; }
.block11{ @test16@: @propvalue16@; }
.block12{ @test17@: @propvalue17@; }
#block13:pseudo
{
    @test18@: @propvalue18@;
    @test19@: @propvalue19@;
}

]]></style>
</html>
"""
        converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, None)
        test_content = self.generate_test_content_properties_and_values(converter.prefixed_properties, converter.prefixed_property_values, 20, test_html)

        oc = OutputCapture()
        oc.capture_output()
        try:
            converter.feed(test_content[2])
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_conversion_happened(converted)
        self.verify_prefixed_properties(converted, test_content[0])
        self.verify_prefixed_property_values(converted, test_content[1])

    def test_convert_attributes_if_needed(self):
        """ Tests convert_attributes_if_needed() using a reference file that has some relative src paths """

        test_html = """<html>
<head>
<script src="../../some-script.js"></script>
<style src="../../../some-style.css"></style>
</head>
<body>
<img src="../../../../some-image.jpg">
</body>
</html>
"""
        test_reference_support_info = {'reference_relpath': '../', 'files': ['../../some-script.js', '../../../some-style.css', '../../../../some-image.jpg'], 'elements': ['script', 'style', 'img']}
        converter = _W3CTestConverter(DUMMY_PATH, DUMMY_FILENAME, test_reference_support_info)

        oc = OutputCapture()
        oc.capture_output()
        try:
            converter.feed(test_html)
            converter.close()
            converted = converter.output()
        finally:
            oc.restore_output()

        self.verify_conversion_happened(converted)
        self.verify_reference_relative_paths(converted, test_reference_support_info)

    def verify_conversion_happened(self, converted):
        self.assertTrue(converted, "conversion didn't happen")

    def verify_no_conversion_happened(self, converted, original):
        self.assertEqual(converted[2], original, 'test should not have been converted')

    def verify_test_harness_paths(self, converter, converted, test_path, num_src_paths, num_href_paths):
        if isinstance(converted, str) or isinstance(converted, unicode):
            converted = BeautifulSoup(converted)

        resources_dir = converter.path_from_webkit_root("LayoutTests", "resources")

        # Verify the original paths are gone, and the new paths are present.
        orig_path_pattern = re.compile('\"/resources/testharness')
        self.assertEquals(len(converted.findAll(src=orig_path_pattern)), 0, 'testharness src path was not converted')
        self.assertEquals(len(converted.findAll(href=orig_path_pattern)), 0, 'testharness href path was not converted')

        new_relpath = os.path.relpath(resources_dir, test_path)
        relpath_pattern = re.compile(new_relpath)
        self.assertEquals(len(converted.findAll(src=relpath_pattern)), num_src_paths, 'testharness src relative path not correct')
        self.assertEquals(len(converted.findAll(href=relpath_pattern)), num_href_paths, 'testharness href relative path not correct')

    def verify_prefixed_properties(self, converted, test_properties):
        self.assertEqual(len(set(converted[0])), len(set(test_properties)), 'Incorrect number of properties converted')
        for test_prop in test_properties:
            self.assertTrue((test_prop in converted[2]), 'Property ' + test_prop + ' not found in converted doc')

    def verify_prefixed_property_values(self, converted, test_property_values):
        self.assertEqual(len(set(converted[1])), len(set(test_property_values)), 'Incorrect number of property values converted ' + str(len(set(converted[1]))) + ' vs ' + str(len(set(test_property_values))))
        for test_value in test_property_values:
            self.assertTrue((test_value in converted[2]), 'Property value ' + test_value + ' not found in converted doc')

    def verify_reference_relative_paths(self, converted, reference_support_info):
        idx = 0
        for path in reference_support_info['files']:
            expected_path = re.sub(reference_support_info['reference_relpath'], '', path, 1)
            element = reference_support_info['elements'][idx]
            expected_tag = '<' + element + ' src=\"' + expected_path + '\">'
            self.assertTrue(expected_tag in converted[2], 'relative path ' + path + ' was not converted correcty')
            idx += 1

    def generate_test_content_properties_and_values(self, full_property_list, fully_property_values_list, num_test_properties_and_values, html):
        """Inserts properties requiring a -webkit- prefix into the content, replacing \'@testXX@\' with a property and \'@propvalueXX@\' with a value."""
        test_content_properties = self.generate_test_content(full_property_list, num_test_properties_and_values, 'test', html)
        test_content_property_values = self.generate_test_content(fully_property_values_list, num_test_properties_and_values, 'propvalue', test_content_properties[1])
        return (test_content_properties[0], test_content_property_values[0], test_content_property_values[1])

    def generate_test_content(self, full_list, num_test, suffix, html):
        test_list = []
        count = 0
        while count < num_test:
            test_list.append(full_list[count])
            count += 1

        # Replace the tokens in the testhtml with the test properties or values.
        # Walk backward through the list to replace the double-digit tokens first.
        index = len(test_list) - 1
        while index >= 0:
            # Use the unprefixed version
            test = test_list[index].replace('-webkit-', '')
            # Replace the token
            html = html.replace('@' + suffix + str(index) + '@', test)
            index -= 1

        return (test_list, html)
