import re
from mako import compat
from mako import lexer
from mako import parsetree


class MessageExtractor(object):
    def process_file(self, fileobj):
        template_node = lexer.Lexer(fileobj.read(),
                                    input_encoding=self.config['encoding']).parse()
        for extracted in self.extract_nodes(template_node.get_children()):
            yield extracted

    def extract_nodes(self, nodes):
        translator_comments = []
        in_translator_comments = False
        comment_tags = filter(None, re.split(r'\s+', self.config['comment-tags']))

        for node in nodes:
            child_nodes = None
            if in_translator_comments and isinstance(node, parsetree.Text) and \
                    not node.content.strip():
                # Ignore whitespace within translator comments
                continue

            if isinstance(node, parsetree.Comment):
                value = node.text.strip()
                if in_translator_comments:
                    translator_comments.extend(self._split_comment(node.lineno, value))
                    continue
                for comment_tag in comment_tags:
                    if value.startswith(comment_tag):
                        in_translator_comments = True
                        translator_comments.extend(self._split_comment(node.lineno,
                                                                  value))
                continue

            if isinstance(node, parsetree.DefTag):
                code = node.function_decl.code
                child_nodes = node.nodes
            elif isinstance(node, parsetree.BlockTag):
                code = node.body_decl.code
                child_nodes = node.nodes
            elif isinstance(node, parsetree.CallTag):
                code = node.code.code
                child_nodes = node.nodes
            elif isinstance(node, parsetree.PageTag):
                code = node.body_decl.code
            elif isinstance(node, parsetree.CallNamespaceTag):
                code = node.expression
                child_nodes = node.nodes
            elif isinstance(node, parsetree.ControlLine):
                if node.isend:
                    in_translator_comments = False
                    continue
                code = node.text
            elif isinstance(node, parsetree.Code):
                in_translator_comments = False
                code = node.code.code
            elif isinstance(node, parsetree.Expression):
                code = node.code.code
            else:
                continue

            # Comments don't apply unless they immediately preceed the message
            if translator_comments and \
                    translator_comments[-1][0] < node.lineno - 1:
                translator_comments = []

            translator_strings = [comment[1] for comment in translator_comments]

            if isinstance(code, compat.text_type):
                code = code.encode('ascii', 'backslashreplace')

            used_translator_comments = False
            code = compat.byte_buffer(code)
            for message in self.process_python(code, node.lineno, translator_strings):
                yield message
                used_translator_comments = True

            if used_translator_comments:
                translator_comments = []
            in_translator_comments = False

            if child_nodes:
                for extracted in self.extract_nodes(child_nodes):
                    yield extracted

    @staticmethod
    def _split_comment(lineno, comment):
        """Return the multiline comment at lineno split into a list of comment line
        numbers and the accompanying comment line"""
        return [(lineno + index, line) for index, line in
                enumerate(comment.splitlines())]
