"""
modul textdiff - provides text-difference tools

It contains class TextDiff.
"""
import misc, difflib2, string, re

__all__=['classical_diff','context_diff','html_diff','normal_diff',
         'unified_diff']

class TextDiff:
    r"""Class, which provides interfaces to text-differencing tools."""

    def __init__(self,file1_name='',file2_name='',param=None,text1='',text2 = ''):
        r"""Constructs TextDiff instance.

        parameters:
        file1_name - name of the first file
        file2_name - name of the second file
        param - options from optparse
        text1, text2 - if they are defined, compared are texts instead files

        instance variables:
        self.file1_name - name of the first file
        self.file2_name - name of the second file
        self.lines1 - text of the first file
        self.lines2 - text of the second file
        self.options - options from optparse
        """
        self.param=param            #options from command line


        self.file1_name=file1_name  #from file name
        self.file2_name=file2_name  #to file name

        if text1 != '' and text2 != '':
            self.lines1 = text1
            self.lines2 = text2
        else:
            self.file1=misc.open_file(self.file1_name) #file descriptors
            self.file2=misc.open_file(self.file2_name)

            self.lines1=self.file1.readlines()         #list of lines
            self.lines2=self.file2.readlines()

            self.file1.close()
            self.file2.close()

        self.file1_date=misc.get_date(self.file1_name)
        self.file2_date=misc.get_date(self.file2_name)

        def remove_blank_lines(lines):
            """Removes all blank lines from `lines`"""
            pat_remove_blank_lines = re.compile(r'^\s+$')

            l = len(lines)
            for i in reversed(range(l)):
                if lines[i] == '\n':
                    del lines[i]

        def remove_matching_lines(lines,pattern):
            """Removes all lines matching with regular expression from
            `pattern`
            """
            pat_remove_matching_lines = re.compile(pattern)

            l = len(lines)
            for i in reversed(range(l)):
                if pat_remove_matching_lines.match(lines[i]):
                    del lines[i]

        if self.param.ignore_blank_lines or self.param.ignore_all_space:
            remove_blank_lines(self.lines1)
            remove_blank_lines(self.lines2)

        if self.param.ignore_matching_lines != '':
            remove_matching_lines(self.lines1,self.param.ignore_matching_lines)
            remove_matching_lines(self.lines2,self.param.ignore_matching_lines)




    def prepare_lines(self,lines):
        r"""Modifies each line according to options.

        If texts are compared with ignored white space, case insensitive or
        ignoring some words, lines has to be modified.

        If the case sensitivity is ignored, it has to upper all characters.
        If white spaces are ignored, it has to reduce more than one spaces or
        tabs to just one.
        If some words are ignored, it has to delete them.
        """

        if self.param.ignore_case or self.param.ignore_space_change or \
           self.param.ignore_all_space or self.param.ignore_matching_words:

            if self.param.ignore_matching_words:
                for i in range(len(lines)):
                    lines[i] = re.sub(self.param.ignore_matching_words,r'',lines[i])

            #if option --ignore-case, text is converted to lower
            if self.param.ignore_case:
                for i in range(len(lines)):
                    lines[i] = lines[i].lower()

            #if option --ignore-space-change, from text are removed
            #all affluence white spaces
            if self.param.ignore_space_change or self.param.ignore_all_space:
                for i in range(len(lines)):
                    lines[i] = re.sub(r'[ \t]+',r' ',lines[i])

    #interfaces to functions to modified difflib - difflib2
    def unified_diff(self):
        return difflib2.unified_diff(self.lines1, self.lines2,
                                     self.file1_name, self.file2_name,
                                     self.file1_date, self.file2_date,
                                     n=self.param.context, lineterm='\n',
                                     prepare=self.prepare_lines)

    def context_diff(self):
        return difflib2.context_diff(self.lines1, self.lines2,
                                    self.file1_name, self.file2_name,
                                    self.file1_date, self.file2_date,
                                    n=self.param.context,
                                    prepare=self.prepare_lines)

    def normal_diff(self):
        return difflib2.ndiff(self.lines1, self.lines2,
                              prepare=self.prepare_lines)

    def gnu_diff(self):
        return difflib2.gnu_diff(self.lines1, self.lines2,
                                 prepare=self.prepare_lines)

    def html_diff(self):
        return difflib2.HtmlDiff().make_file(self.lines1, self.lines2,
                                            self.file1_name,self.file2_name,
                                            context=self.param.context_diff,
                                            numlines=self.param.context)






