#!/usr/bin/env python
#
# Copyright (C) 2011 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.

import codecs
import logging
import os
import os.path
import re
import sys

from webkitpy.common.checkout.scm import SCMDetector
from webkitpy.common.system.filesystem import FileSystem
from webkitpy.common.system.executive import Executive
from webkitpy.common.system.logutils import configure_logging
from webkitpy.style.checker import ProcessorBase
from webkitpy.style.filereader import TextFileReader
from webkitpy.style.main import change_directory

_inspector_directory = "Source/WebCore/inspector/front-end"
_localized_strings = "Source/WebCore/English.lproj/localizedStrings.js"

_log = logging.getLogger("check-inspector-strings")

class StringsExtractor(ProcessorBase):
    def __init__(self, patterns):
        self._patterns = patterns
        self.strings = []
        for p in self._patterns:
            self.strings.append([])

    def should_process(self, file_path):
        return file_path.endswith(".js") and (not file_path.endswith("InjectedScript.js"))

    def process(self, lines, file_path, line_numbers=None):
        for line in lines:
            comment_start = line.find("//")
            if comment_start != -1:
                line = line[:comment_start]
            index = 0
            for pattern in self._patterns:
                line_strings = re.findall(pattern, line)
                for string in line_strings:
                    self.strings[index].append(string)
                index += 1

class LocalizedStringsExtractor:
    def __init__(self):
        self.localized_strings = []

    def process_file(self, file_path):
        localized_strings_file = codecs.open(file_path, encoding="utf-8", mode="r")
        try:
            contents = localized_strings_file.read()
            lines = contents.split("\n")
            for line in lines:
                match = re.match(r"localizedStrings\[\"((?:[^\"\\]|\\.)*?)\"", line)
                if match:
                    self.localized_strings.append(match.group(1))
        finally:
            localized_strings_file.close()

def extract_ui_strings(str, out):
    line_unrecognized = False
    idx = 0
    while idx < len(str):
        idx = str.find("WI.UIString(", idx)
        if idx == -1:
            break
        idx = idx + len("WI.UIString(")
        balance = 1
        item_recognized = False
        while idx < len(str):
            if str[idx] == ')':
                balance = balance - 1
                if balance == 0:
                    break
            elif str[idx] == '(':
                balance = balance + 1
            elif balance == 1:
                if str[idx] == ',':
                    break
                elif str[idx] == '"':
                    str_idx = idx + 1
                    while str_idx < len(str):
                        if str[str_idx] == '\\':
                            str_idx = str_idx + 1
                        elif str[str_idx] == '"':
                            out.add(str[idx + 1 : str_idx])
                            idx = str_idx
                            item_recognized = True
                            break
                        str_idx = str_idx + 1
            idx = idx + 1
        if not item_recognized:
            line_unrecognized = True
    if line_unrecognized:
        _log.info("Unrecognized: %s" % str)

if __name__ == "__main__":
    configure_logging()

    cwd = os.path.abspath(os.curdir)
    filesystem = FileSystem()
    scm = SCMDetector(filesystem, Executive()).detect_scm_system(cwd)

    if scm is None:
        _log.error("WebKit checkout not found: You must run this script "
                   "from within a WebKit checkout.")
        sys.exit(1)

    checkout_root = scm.checkout_root
    _log.debug("WebKit checkout found with root: %s" % checkout_root)
    change_directory(filesystem, checkout_root=checkout_root, paths=None)

    strings_extractor = StringsExtractor([r"(WI\.UIString\(.*)", r"\"((?:[^\"\\]|\\.)*?)\""])
    file_reader = TextFileReader(filesystem, strings_extractor)
    file_reader.process_paths([_inspector_directory])
    localized_strings_extractor = LocalizedStringsExtractor()
    localized_strings_extractor.process_file(_localized_strings)
    raw_ui_strings = frozenset(strings_extractor.strings[0])
    ui_strings = set()
    for s in raw_ui_strings:
        extract_ui_strings(s, ui_strings)
    strings = frozenset(strings_extractor.strings[1])
    localized_strings = frozenset(localized_strings_extractor.localized_strings)

    new_strings = ui_strings - localized_strings
    for s in new_strings:
        _log.info("New: \"%s\"" % (s))
    old_strings = localized_strings - ui_strings
    suspicious_strings = strings & old_strings
    for s in suspicious_strings:
        _log.info("Suspicious: \"%s\"" % (s))
    unused_strings = old_strings - strings
    for s in unused_strings:
        _log.info("Unused: \"%s\"" % (s))

    localized_strings_duplicates = {}
    for s in localized_strings_extractor.localized_strings:
        if s in localized_strings_duplicates:
            _log.info("Duplicate: \"%s\"" % (s))
        else:
            localized_strings_duplicates.setdefault(s)
