# 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 json
import logging
import os
import re
import sys

from webkitpy.common.host import Host
from webkitpy.common.webkit_finder import WebKitFinder

if sys.version_info > (3, 0):
    from html.parser import HTMLParser
else:
    from HTMLParser import HTMLParser

_log = logging.getLogger(__name__)


def convert_for_webkit(new_path, filename, reference_support_info, host=Host(), convert_test_harness_links=True, webkit_test_runner_options=''):
    """ Converts a file's |contents| so it will function correctly in its |new_path| in Webkit.

    Returns the list of modified properties and the modified text if the file was modifed, None otherwise."""
    contents = host.filesystem.read_text_file(filename)

    # WebKit does not have a www test domain.
    contents = contents.replace('{{domains[www]}}', '{{hosts[alt][]}}')

    converter = _W3CTestConverter(new_path, filename, reference_support_info, host, convert_test_harness_links, webkit_test_runner_options)
    if filename.endswith('.css'):
        return converter.add_webkit_prefix_to_unprefixed_properties_and_values(contents)
    elif filename.endswith('.js'):
        return ([], [], contents)
    else:
        converter.feed(contents)
        converter.close()
        return converter.output()


class _W3CTestConverter(HTMLParser):
    def __init__(self, new_path, filename, reference_support_info, host=Host(), convert_test_harness_links=True, webkit_test_runner_options=''):
        if sys.version_info > (3, 0):
            HTMLParser.__init__(self, convert_charrefs=False)
        else:
            HTMLParser.__init__(self)

        self._host = host
        self._filesystem = self._host.filesystem
        self._webkit_root = WebKitFinder(self._filesystem).webkit_base()

        self.converted_data = []
        self.converted_properties = []
        self.converted_property_values = []
        self.in_style_tag = False
        self.style_data = []
        self.filename = filename
        self.reference_support_info = reference_support_info
        self.webkit_test_runner_options = webkit_test_runner_options
        self.has_started = False

        resources_path = self.path_from_webkit_root('LayoutTests', 'resources')
        resources_relpath = self._filesystem.relpath(resources_path, new_path)
        self.new_test_harness_path = resources_relpath.replace(os.sep, '/')
        self.convert_test_harness_links = convert_test_harness_links

        # These settings might vary between WebKit and Blink
        css_property_file = self.path_from_webkit_root('Source', 'WebCore', 'css', 'CSSProperties.json')
        css_property_value_file = self.path_from_webkit_root('Source', 'WebCore', 'css', 'CSSValueKeywords.in')

        self.test_harness_re = re.compile('/resources/testharness')

        self.prefixed_properties = self.read_webkit_prefixed_css_property_list(css_property_file)
        prop_regex = r'([\s{]|^)(' + "|".join(prop.replace('-webkit-', '') for prop in self.prefixed_properties) + r')(\s+:|:)'
        self.prop_re = re.compile(prop_regex)

        self.prefixed_property_values = self.legacy_read_webkit_prefixed_css_property_list(css_property_value_file)
        prop_value_regex = r'(:\s*|^\s*)(' + "|".join(value.replace('-webkit-', '') for value in self.prefixed_property_values) + r')(\s*;|\s*}|\s*$)'
        self.prop_value_re = re.compile(prop_value_regex)

    def output(self):
        return (self.converted_properties, self.converted_property_values, ''.join(self.converted_data))

    def path_from_webkit_root(self, *comps):
        return self._filesystem.abspath(self._filesystem.join(self._webkit_root, *comps))

    def read_webkit_prefixed_css_property_list(self, file_name):
        contents = self._filesystem.read_text_file(file_name)
        if not contents:
            return []
        properties = json.loads(contents)['properties']
        property_names = []
        for property_name, property_dict in properties.items():
            property_names.append(property_name)
            if 'codegen-properties' in property_dict:
                codegen_options = property_dict['codegen-properties']
                if 'aliases' in codegen_options:
                    property_names.extend(codegen_options['aliases'])

        prefixed_properties = []
        unprefixed_properties = set()
        for property_name in property_names:
            # Find properties starting with the -webkit- prefix.
            match = re.match(r'-webkit-([\w|-]*)', property_name)
            if match:
                prefixed_properties.append(match.group(1))
            else:
                unprefixed_properties.add(property_name)

        # Ignore any prefixed properties for which an unprefixed version is supported
        return [prop for prop in prefixed_properties if prop not in unprefixed_properties]

    def legacy_read_webkit_prefixed_css_property_list(self, file_name):
        contents = self._filesystem.read_text_file(file_name)
        prefixed_properties = []
        unprefixed_properties = set()

        for line in contents.splitlines():
            if re.match('^(#|//)', line) or len(line.strip()) == 0:
                # skip comments and preprocessor directives and empty lines.
                continue
            # Property name is always first on the line.
            property_name = line.split(' ', 1)[0]
            # Find properties starting with the -webkit- prefix.
            match = re.match(r'-webkit-([\w|-]*)', property_name)
            if match:
                prefixed_properties.append(match.group(1))
            else:
                unprefixed_properties.add(property_name.strip())

        # Ignore any prefixed properties for which an unprefixed version is supported
        return [prop for prop in prefixed_properties if prop not in unprefixed_properties]

    def add_webkit_prefix_to_unprefixed_properties_and_values(self, text):
        """ Searches |text| for instances of properties and values requiring the -webkit- prefix and adds the prefix to them.

        Returns the list of converted properties, values and the modified text."""

        converted_properties = self.add_webkit_prefix_following_regex(text, self.prop_re)
        converted_property_values = self.add_webkit_prefix_following_regex(converted_properties[1], self.prop_value_re)

        # FIXME: Handle the JS versions of these properties and values and GetComputedStyle, too.
        return (converted_properties[0], converted_property_values[0], converted_property_values[1])

    def add_webkit_prefix_following_regex(self, text, regex):
        converted_list = set()
        text_chunks = []
        cur_pos = 0
        for m in regex.finditer(text):
            text_chunks.extend([text[cur_pos:m.start()], m.group(1), '-webkit-', m.group(2), m.group(3)])
            converted_list.add(m.group(2))
            cur_pos = m.end()
        text_chunks.append(text[cur_pos:])

        for item in converted_list:
            _log.info('  converting %s', item)

        return (converted_list, ''.join(text_chunks))

    def convert_reference_relpaths(self, text):
        """ Searches |text| for instances of files in reference_support_info and updates the relative path to be correct for the new ref file location"""
        converted = text
        for path in self.reference_support_info['files']:
            if converted.find(path) != -1:
                # FIXME: This doesn't handle an edge case where simply removing the relative path doesn't work.
                # See http://webkit.org/b/135677 for details.
                new_path = re.sub(re.escape(self.reference_support_info['reference_relpath']), '', path, 1)
                converted = re.sub(re.escape(path), new_path, converted)

        return converted

    def convert_style_data(self, data):
        converted = self.add_webkit_prefix_to_unprefixed_properties_and_values(data)
        if converted[0]:
            self.converted_properties.extend(list(converted[0]))
        if converted[1]:
            self.converted_property_values.extend(list(converted[1]))

        if self.reference_support_info is None or self.reference_support_info == {}:
            return converted[2]

        return self.convert_reference_relpaths(converted[2])

    def convert_attributes_if_needed(self, tag, attrs):
        converted = self.get_starttag_text()
        if self.convert_test_harness_links and tag in ('script', 'link'):
            attr_name = 'src'
            if tag != 'script':
                attr_name = 'href'
            for attr in attrs:
                if attr[0] == attr_name:
                    new_path = re.sub(self.test_harness_re, self.new_test_harness_path + '/testharness', attr[1])
                    converted = re.sub(re.escape(attr[1]), new_path, converted)

        for attr in attrs:
            if attr[0] == 'style':
                new_style = self.convert_style_data(attr[1])
                converted = re.sub(re.escape(attr[1]), new_style, converted)

        # Convert relative paths
        src_tags = ('script', 'style', 'img', 'frame', 'iframe', 'input', 'layer', 'textarea', 'video', 'audio')
        if self.reference_support_info is not None and self.reference_support_info != {}:
            if tag in src_tags:
                for attr_name, attr_value in attrs:
                    if attr_name == 'src':
                        new_path = self.convert_reference_relpaths(attr_value)
                        converted = re.sub(re.escape(attr_value), new_path, converted)
            if tag == 'link':
                for attr_name, attr_value in attrs:
                    if attr_name == 'href':
                        new_path = self.convert_reference_relpaths(attr_value)
                        converted = re.sub(re.escape(attr_value), new_path, converted)
        self.converted_data.append(converted)

    def add_webkit_test_runner_options_if_needed(self):
        if self.has_started:
            return
        self.has_started = True
        if self.webkit_test_runner_options:
            self.converted_data[-1] = self.converted_data[-1] + self.webkit_test_runner_options

    def handle_starttag(self, tag, attrs):
        if tag == 'style':
            self.in_style_tag = True
        self.convert_attributes_if_needed(tag, attrs)
        self.add_webkit_test_runner_options_if_needed()

    def handle_endtag(self, tag):
        if tag == 'style':
            self.converted_data.append(self.convert_style_data(''.join(self.style_data)))
            self.in_style_tag = False
            self.style_data = []
        self.converted_data.extend(['</', tag, '>'])

    def handle_startendtag(self, tag, attrs):
        self.convert_attributes_if_needed(tag, attrs)

    def handle_data(self, data):
        if self.in_style_tag:
            self.style_data.append(data)
        else:
            self.converted_data.append(data)

    def handle_entityref(self, name):
        self.converted_data.extend(['&', name, ';'])

    def handle_charref(self, name):
        self.converted_data.extend(['&#', name, ';'])

    def handle_comment(self, data):
        self.converted_data.extend(['<!--', data, '-->'])
        self.add_webkit_test_runner_options_if_needed()

    def handle_decl(self, decl):
        self.converted_data.extend(['<!', decl, '>'])
        self.add_webkit_test_runner_options_if_needed()

    def handle_pi(self, data):
        self.converted_data.extend(['<?', data, '>'])
        self.add_webkit_test_runner_options_if_needed()
