import glob
import os
import re
import errno
import shutil


def get_sub_dirs_and_files(path, abs_path=False):
    """
    Gets the direct child sub-files and sub-folders of the given directory

    Args:
        path: Absolute path to the directory
        abs_path: If set to True, it returns a list of absolute paths to the sub-directories and
                    sub-files instead of directory names only

    Returns:

        dict: {"folders": [list of (if abs_path is True, then path to) sub-folders],
               "files": [list of (if abs_path is True, then path to) sub-files]}

    """
    folders = get_sub_folders(path, abs_path=abs_path)
    files = get_sub_files(path, abs_path=abs_path)
    return {"folders": folders, "files": files}


def get_sub_folders(path, abs_path=False):
    """
    Gets the direct child sub-folders of the given directory
    Args:
        path: Absolute path to the directory
        abs_path: If set to True, it returns a list of absolute paths to the sub-directories
                  instead of directory names only

    Returns:
        only_folders: [list of sub-folders]

    """
    folders = []
    temp = glob.glob(path + os.sep + "*")
    for folder in temp:
        if os.path.isdir(folder) and not folder.endswith('__pycache__'):
            folders.append(folder)
    only_folders = [f.replace("\\", '/') for f in folders]
    if not abs_path:
        only_folders = [f.rpartition('/')[2] for f in only_folders]
    return only_folders


def get_sub_files(path, abs_path=False):
    """
    Gets the direct child sub-files of the given directory
    Args:
        path: Absolute path to the directory
        abs_path: If set to True, it returns a list of absolute paths to the sub-files instead of
                  file names only

    Returns:
        only_files: [list of sub-files]

    """
    files = glob.glob(path + os.sep + "*.*")
    only_files = [f.replace("\\", '/') for f in files]
    if not abs_path:
        only_files = [f.rpartition('/')[2] for f in only_files]
    return only_files


def get_abs_path(relative_path, base_path=None, silence_error=False):
    """
    Gets the absolute path from the given relative_path and base_path
    Args:
        relative_path: relative path to the file/directory
        base_path: absolute path from where the relative path should be traced. If not provided, the
                   current working directory path will be used.
        silence_error: Setting this to True would not verify if the directory exists

    Returns:
        path: absolute path derived from relative_path and base_path

    """
    if base_path is None:
        base_path = os.getcwd()

    path = os.path.join(base_path.strip(), relative_path.strip())

    if not silence_error and not os.path.exists(path):
        print("An Error Occurred: {0} does not exist".format(path))
        path = None

    return path


def get_parent_directory(directory_path, level=1):
    """
    Gets the parent directory
    Args:
        directory_path: Absolute path to the file/dir who's parent needs to be returned
        level: Indicates how many levels up to go to find the parent
               eg: default of 1 goes one level up (to the parent directory)
               level=2 would get the grandparent directory

    Returns:

    """
    if directory_path.endswith(os.sep):
        directory_path = directory_path[:-1]
    for i in range(0, level):
        directory_path = os.path.dirname(directory_path)
    return directory_path


def get_paths_of_subfiles(parent_dir, extension=re.compile("\..*")):
    """
    This function returns a list of all the sub-files inside the given directory

    Args:
        parent_dir: Absolute path to the directory
        extension: Regular Expression tha would match a file extension. If not provided, file paths
                   of all extension will be returned

    Returns:
        file_path: Returns a list of paths to sub-files inside the parent_dir

    """
    file_paths = []
    sub_files_and_folders = get_sub_dirs_and_files(parent_dir, abs_path=True)
    for sub_file in sub_files_and_folders["files"]:
        if extension.match(os.path.splitext(sub_file)[1]):
            file_paths.append(sub_file)
    for sub_folder in sub_files_and_folders["folders"]:
        file_paths.extend(get_paths_of_subfiles(sub_folder, extension=extension))
    return file_paths


def get_dir_from_path(path):
    """
    This function is wrapper function for os.path.basename.

    Args:
        path: a file path [Eg: /home/user/Documents/GitHub/warriorframework]

    Returns:
        The base directory name: [Eg: warriorframework]
    """
    return os.path.basename(path)


def get_parent_dir_path(path):
    """
    This function is wrapper function for os.path.dirname(os.path.normpath(<path>)).

    Args:
        path: a file path [Eg: /home/user/Documents/GitHub/warriorframework]

    Returns:
        The parent directory path: [Eg: /home/user/Documents/GitHub]
    """
    return os.path.dirname(os.path.normpath(path))


def join_path(path, *paths):
    """
    This function is wrapper function for os.path.join.

    Args:
        path: a file path
        *paths: paths to be joined to the file path above

    Returns:
        Joined path
    """
    return os.path.join(path, *paths)


def get_relative_path(path, start_directory):
    """
    This is a wrapper function for the os.path.relpath

    Args:
        path: Absolute path to the file/dir to which the relatove path needs to be calculated.
        start_directory: The absolute path to the starting directory

    Returns:
         rel_path: A relative path from start_directory

    """
    if start_directory == "":
        print("-- Error -- start_directory is empty.")
        relpath = path
    else:
        try:
            relpath = os.path.relpath(path, start_directory)
        except Exception as e:
            print("-- Error -- {0}".format(e))
            relpath = None
        else:
            if not relpath.startswith(".") and not relpath.startswith(os.sep):
                relpath = os.sep + relpath
    return relpath


def create_dir(path):
    output = path
    try:
        os.makedirs(path)
    except OSError as exception:
        if exception.errno != errno.EEXIST:
            output = False
            print("-- A Error Occurred -- {0}".format(exception))
    return output


def delete_dir(src):
    output = True
    try:
        shutil.rmtree(src)
    except Exception as e:
        print(e)
        output = False
    return output


def file_or_dir_exists(filepath):
    output = False
    if os.path.exists(filepath):
        output = True
    return output


def get_direct_sub_files(path, abs_path=False, extension=re.compile("\..*")):
    """
    Gets the direct child sub-files of the given directory
    Args:
        path: Absolute path to the directory
        abs_path: If set to True, it returns a list of absolute paths to the sub-files instead of
                  file names only

    Returns:
        only_files: [list of sub-files]

    """
    files = glob.glob(path + os.sep + "*.*")
    only_files = [f.replace("\\", '/') for f in files]
    if not abs_path:
        only_files = [f.rpartition('/')[2] for f in only_files]
    final_files = []
    for sub_file in only_files:
        if extension.match(os.path.splitext(sub_file)[1]):
            final_files.append(sub_file)
    return final_files

[((41, 11, 41, 41), 'glob.glob', 'glob.glob', ({(41, 21, 41, 40): "path + os.sep + '*'"}, {}), "(path + os.sep + '*')", False, 'import glob\n'), ((63, 12, 63, 44), 'glob.glob', 'glob.glob', ({(63, 22, 63, 43): "path + os.sep + '*.*'"}, {}), "(path + os.sep + '*.*')", False, 'import glob\n'), ((114, 48, 114, 66), 're.compile', 're.compile', ({(114, 59, 114, 65): '"""\\\\..*"""'}, {}), "('\\\\..*')", False, 'import re\n'), ((147, 11, 147, 33), 'os.path.basename', 'os.path.basename', ({(147, 28, 147, 32): 'path'}, {}), '(path)', False, 'import os\n'), ((174, 11, 174, 37), 'os.path.join', 'os.path.join', ({(174, 24, 174, 28): 'path', (174, 30, 174, 36): '*paths'}, {}), '(path, *paths)', False, 'import os\n'), ((227, 7, 227, 31), 'os.path.exists', 'os.path.exists', ({(227, 22, 227, 30): 'filepath'}, {}), '(filepath)', False, 'import os\n'), ((232, 57, 232, 75), 're.compile', 're.compile', ({(232, 68, 232, 74): '"""\\\\..*"""'}, {}), "('\\\\..*')", False, 'import re\n'), ((244, 12, 244, 44), 'glob.glob', 'glob.glob', ({(244, 22, 244, 43): "path + os.sep + '*.*'"}, {}), "(path + os.sep + '*.*')", False, 'import glob\n'), ((84, 20, 84, 31), 'os.getcwd', 'os.getcwd', ({}, {}), '()', False, 'import os\n'), ((110, 25, 110, 56), 'os.path.dirname', 'os.path.dirname', ({(110, 41, 110, 55): 'directory_path'}, {}), '(directory_path)', False, 'import os\n'), ((160, 27, 160, 49), 'os.path.normpath', 'os.path.normpath', ({(160, 44, 160, 48): 'path'}, {}), '(path)', False, 'import os\n'), ((207, 8, 207, 25), 'os.makedirs', 'os.makedirs', ({(207, 20, 207, 24): 'path'}, {}), '(path)', False, 'import os\n'), ((218, 8, 218, 26), 'shutil.rmtree', 'shutil.rmtree', ({(218, 22, 218, 25): 'src'}, {}), '(src)', False, 'import shutil\n'), ((43, 11, 43, 32), 'os.path.isdir', 'os.path.isdir', ({(43, 25, 43, 31): 'folder'}, {}), '(folder)', False, 'import os\n'), ((88, 33, 88, 53), 'os.path.exists', 'os.path.exists', ({(88, 48, 88, 52): 'path'}, {}), '(path)', False, 'import os\n'), ((194, 22, 194, 60), 'os.path.relpath', 'os.path.relpath', ({(194, 38, 194, 42): 'path', (194, 44, 194, 59): 'start_directory'}, {}), '(path, start_directory)', False, 'import os\n'), ((130, 27, 130, 53), 'os.path.splitext', 'os.path.splitext', ({(130, 44, 130, 52): 'sub_file'}, {}), '(sub_file)', False, 'import os\n'), ((250, 27, 250, 53), 'os.path.splitext', 'os.path.splitext', ({(250, 44, 250, 52): 'sub_file'}, {}), '(sub_file)', False, 'import os\n')]