# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See LICENSE in the project root
# for license information.

from __future__ import print_function, with_statement, absolute_import, unicode_literals

from glob import glob
import os.path
import platform


MAX_FILES_TO_CACHE = 1000


class PathUnNormcase(object):
    """Ensures path names of files are returned as they exist on the fs."""

    def __init__(self):
        self._dict = {}
        self._enabled = False

    def enable(self):
        self._enabled = platform.system() == 'Windows'

    def un_normcase(self, file_path):
        if not self._enabled or len(file_path) == 0:
            return file_path
        if file_path in self._dict:
            return self._dict[file_path]
        file_path_to_return = self._get_actual_filename(file_path)
        self.track_file_path_case(file_path_to_return)
        return file_path_to_return

    def track_file_path_case(self, file_path):
        if not self._enabled:
            return
        if len(self._dict) > MAX_FILES_TO_CACHE:
            self._dict.clear()
        self._dict[file_path] = file_path

    def _get_actual_filename(self, name):
        """
        Use glob to search for a file by building a regex.
        Original source from https://stackoverflow.com/a/30374360/4443457
        (Modified to match file name as well).
        """

        sep = os.path.sep
        parts = os.path.normpath(name).split(sep)
        dirs = parts[0:-1]
        filename = '{}[{}]'.format(parts[-1][:-1], parts[-1][-1:])
        path_fragment1 = dirs[0].upper()
        if dirs[0] == os.path.splitdrive(name)[0]:
            fragments = [path_fragment1]
        else:
            dir_names = os.listdir(os.getcwd())
            fragments = list(filter(
                            lambda x: x.upper() == path_fragment1, dir_names))
        fragments += list('{}[{}]'.format(d[:-1], d[-1])
                          for d in dirs[1:] if d)
        path = glob(sep.join(fragments))
        if not path:
            return name
        res = glob(sep.join((path[0], filename)))
        if not res:
            return name
        return res[0]
