# Copyright (C) 2010 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.

"""Wrapper object for the file system / source tree."""

import codecs
import errno
import filecmp
import glob
import hashlib
import os
import shutil
import sys
import tempfile
import time

from webkitpy.common.unicode_compatibility import decode_if_necessary


class FileSystem(object):
    """FileSystem interface for webkitpy.

    Unless otherwise noted, all paths are allowed to be either absolute
    or relative."""
    sep = os.sep
    pardir = os.pardir

    def abspath(self, path):
        # FIXME: This gross hack is needed while we transition from Cygwin to native Windows, because we
        # have some mixing of file conventions from different tools:
        if sys.platform == 'cygwin':
            path = os.path.normpath(path)
            path_components = path.split(os.sep)
            if path_components and len(path_components[0]) == 2 and path_components[0][1] == ':':
                path_components[0] = path_components[0][0]
                path = os.path.join('/', 'cygdrive', *path_components)

        return os.path.abspath(path)

    def realpath(self, path):
        return os.path.realpath(path)

    def path_to_module(self, module_name):
        """A wrapper for all calls to __file__ to allow easy unit testing."""
        # FIXME: This is the only use of sys in this file. It's possible this function should move elsewhere.
        return sys.modules[module_name].__file__  # __file__ is always an absolute path.

    def expanduser(self, path):
        return os.path.expanduser(path)

    def basename(self, path):
        return os.path.basename(path)

    def chdir(self, path):
        return os.chdir(path)

    def copyfile(self, source, destination):
        shutil.copyfile(source, destination)

    def dirname(self, path):
        return os.path.dirname(path)

    def exists(self, path):
        return os.path.exists(path)

    def dirs_under(self, path, dir_filter=None):
        """Return the list of all directories under the given path in topdown order.

        Args:
            dir_filter: if not None, the filter will be invoked
                with the filesystem object and the path of each dirfound.
                The dir is included in the result if the callback returns True.
        """
        def filter_all(fs, dirpath):
            return True
        dir_filter = dir_filter or filter_all

        dirs = []
        for (dirpath, dirnames, filenames) in os.walk(path):
            if dir_filter(self, dirpath):
                dirs.append(dirpath)
        return dirs

    def files_under(self, path, dirs_to_skip=[], file_filter=None):
        """Return the list of all files under the given path in topdown order.

        Args:
            dirs_to_skip: a list of directories to skip over during the
                traversal (e.g., .svn, resources, etc.)
            file_filter: if not None, the filter will be invoked
                with the filesystem object and the dirname and basename of
                each file found. The file is included in the result if the
                callback returns True.
        """
        def filter_all(fs, dirpath, basename):
            return True

        file_filter = file_filter or filter_all
        files = []
        if self.isfile(path):
            if file_filter(self, self.dirname(path), self.basename(path)):
                files.append(path)
            return files

        if self.basename(path) in dirs_to_skip:
            return []

        for (dirpath, dirnames, filenames) in os.walk(path):
            for d in dirs_to_skip:
                if d in dirnames:
                    dirnames.remove(d)

            for filename in filenames:
                if file_filter(self, dirpath, filename):
                    files.append(self.join(dirpath, filename))
        return files

    def getcwd(self):
        return os.getcwd()

    def glob(self, path):
        return glob.glob(path)

    def isabs(self, path):
        return os.path.isabs(path)

    def isfile(self, path):
        return os.path.isfile(path)

    def getsize(self, path):
        return os.path.getsize(path)

    def isdir(self, path):
        return os.path.isdir(path)

    def join(self, *comps):
        return os.path.join(*comps)

    def listdir(self, path):
        return os.listdir(path)

    def mkdtemp(self, **kwargs):
        """Create and return a uniquely named directory.

        This is like tempfile.mkdtemp, but if used in a with statement
        the directory will self-delete at the end of the block (if the
        directory is empty; non-empty directories raise errors). The
        directory can be safely deleted inside the block as well, if so
        desired.

        Note that the object returned is not a string and does not support all of the string
        methods. If you need a string, coerce the object to a string and go from there.
        """
        class TemporaryDirectory(object):
            def __init__(self, filesystem, **kwargs):
                self._filesystem = filesystem
                self._kwargs = kwargs
                self._directory_path = tempfile.mkdtemp(**self._kwargs)

            def __str__(self):
                return self._directory_path

            def __enter__(self):
                return self._directory_path

            def __exit__(self, type, value, traceback):
                if self._filesystem.exists(self._directory_path):
                    self._filesystem.rmtree(self._directory_path)

        return TemporaryDirectory(self, **kwargs)

    def maybe_make_directory(self, *path):
        """Create the specified directory if it doesn't already exist."""
        try:
            os.makedirs(self.join(*path))
        except OSError as e:
            if e.errno != errno.EEXIST:
                raise

    def move(self, source, destination):
        shutil.move(source, destination)

    def mtime(self, path):
        return os.stat(path).st_mtime

    def normpath(self, path):
        return os.path.normpath(path)

    def open_binary_tempfile(self, suffix):
        """Create, open, and return a binary temp file. Returns a tuple of the file and the name."""
        temp_fd, temp_name = tempfile.mkstemp(suffix)
        f = os.fdopen(temp_fd, 'wb')
        return f, temp_name

    def open_binary_file_for_reading(self, path):
        return codecs.open(path, 'rb')

    def read_binary_file(self, path):
        """Return the contents of the file at the given path as a byte string."""
        with open(path, 'rb') as f:
            return f.read()

    def write_binary_file(self, path, contents):
        with open(path, 'wb') as f:
            f.write(contents)

    def open_text_file_for_reading(self, path, errors='strict'):
        # Note: There appears to be an issue with the returned file objects
        # not being seekable. See http://stackoverflow.com/questions/1510188/can-seek-and-tell-work-with-utf-8-encoded-documents-in-python .
        return codecs.open(path, 'r', 'utf8', errors)

    def open_text_file_for_writing(self, path, should_append=False):
        if should_append:
            return codecs.open(path, 'a', 'utf8')
        return codecs.open(path, 'w', 'utf8')

    def open_stdin(self):
        return codecs.StreamReaderWriter(sys.stdin,
                                             codecs.getreader('utf8'),
                                             codecs.getwriter('utf8'),
                                             'replace')

    def read_text_file(self, path, errors='strict'):
        """Return the contents of the file at the given path as a Unicode string.

        The file is read assuming it is a UTF-8 encoded file with no BOM."""
        with codecs.open(path, 'r', 'utf8', errors=errors) as f:
            return f.read()

    def write_text_file(self, path, contents, errors='strict'):
        """Write the contents to the file at the given location.

        The file is written encoded as UTF-8 with no BOM."""
        with codecs.open(path, 'w', 'utf-8', errors=errors) as f:
            f.write(decode_if_necessary(contents, errors=errors))

    def sha1(self, path):
        contents = self.read_binary_file(path)
        return hashlib.sha1(contents).hexdigest()

    def relpath(self, path, start='.'):
        return os.path.relpath(path, start)

    def remove(self, path, osremove=os.remove):
        """On Windows, if a process was recently killed and it held on to a
        file, the OS will hold on to the file for a short while.  This makes
        attempts to delete the file fail.  To work around that, this method
        will retry for a few seconds until Windows is done with the file."""
        try:
            WinOSError = WindowsError
        except NameError:
            WinOSError = OSError

        retry_timeout_sec = 3.0
        sleep_interval = 0.1
        while True:
            try:
                osremove(path)
                return True
            except WinOSError as e:
                time.sleep(sleep_interval)
                retry_timeout_sec -= sleep_interval
                if retry_timeout_sec < 0:
                    raise e

    def rmtree(self, path):
        """Delete the directory rooted at path, whether empty or not."""
        shutil.rmtree(path, ignore_errors=True)

    def copytree(self, source, destination):
        shutil.copytree(source, destination)

    def split(self, path):
        """Return (dirname, basename + '.' + ext)"""
        return os.path.split(path)

    def splitext(self, path):
        """Return (dirname + os.sep + basename, '.' + ext)"""
        return os.path.splitext(path)

    def compare(self, path1, path2):
        return filecmp.cmp(path1, path2)

    def map_base_host_path(self, path):
        """Returns a path from the base host localized for this host. By default,
        this host assumes it is the base host and maps the path to itself"""
        return path

    def move_to_base_host(self, source, destination):
        """Moves a file from this host to the base host. By default, this host
        assumes it is the base host and will just execute a move."""
        self.move(source, destination)

    def move_from_base_host(self, source, destination):
        """Moves a file from the base host to this host. By default, this host
        assumes it is the base host and will just execute a move."""
        self.move(source, destination)

    def copy_to_base_host(self, source, destination):
        """Copy a file from this host to the base host. By default, this host
        assumes it is the base host and will just execute a copytree/copyfile."""
        if self.isdir(source):
            self.copytree(source, destination)
        else:
            self.copyfile(source, destination)

    def copy_from_base_host(self, source, destination):
        """Copy a file from the base host to this host. By default, this host
        assumes it is the base host and will just execute a copytree/copyfile."""
        if self.isdir(source):
            self.copytree(source, destination)
        else:
            self.copyfile(source, destination)
