#!/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/en.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)
