from __future__ import print_function, unicode_literals, division

import os
import re
import codecs
import xml.etree.ElementTree as et

from . import log


class DirectoryProcessor:
    @staticmethod
    def process(input_dir, output_dir, function):
        """
        Apply function to all files in input_dir and save the resulting ouput
        files in output_dir.

        """
        if not os.path.exists(output_dir):
            os.makedirs(output_dir)
        logger = log.get_global_console_logger()
        logger.info("Processing files in {}.".format(input_dir))
        input_file_names = os.listdir(input_dir)
        for input_file_name in input_file_names:
            logger.debug("Processing {}.".format(input_file_name))
            input_file = os.path.join(input_dir, input_file_name)
            with codecs.open(input_file, "r", encoding="UTF-8") as f:
                input_string = f.read()
            output_string = function(input_string)
            output_file = os.path.join(output_dir, input_file_name)
            with codecs.open(output_file, "w", encoding="UTF-8") as f:
                f.write(output_string)
        logger.info("Saved processed files to {}.".format(output_dir))


def str_from_file(path):
    """
    Return file contents as string.

    """
    with open(path) as f:
        s = f.read().strip()
    return s


def xml_equal(xml_file1, xml_file2):
    """
    Parse xml and convert to a canonical string representation so we don't
    have to worry about semantically meaningless differences

    """

    def canonical(xml_file):
        # poor man's canonicalization, since we don't want to install
        # external packages just for unittesting
        s = et.tostring(et.parse(xml_file).getroot()).decode("UTF-8")
        s = re.sub("[\n|\t]*", "", s)
        s = re.sub("\s+", " ", s)
        s = "".join(sorted(s)).strip()
        return s

    return canonical(xml_file1) == canonical(xml_file2)


def list_files(dir_path, recursive=True):
    """
    Return a list of files in dir_path.

    """

    for root, dirs, files in os.walk(dir_path):
        file_list = [os.path.join(root, f) for f in files]
        if recursive:
            for dir in dirs:
                dir = os.path.join(root, dir)
                file_list.extend(list_files(dir, recursive=True))
        return file_list


def verify_dir(path, name=None):
    if name:
        name_str = "Cannot set {} directory because t".format(name)
    else:
        name_str = "T"
    msg = "{}he path {} does not exist.".format(name_str, path)
    if not os.path.exists(path):
        raise Exception(msg)
