# AUTOGENERATED! DO NOT EDIT! File to edit: utils.ipynb (unless otherwise specified).

__all__ = ['function', 'T', 'identity', 'simplify', 'listify', 'setify', 'tuplify', 'merge_tfms', 'compose', 'pipe',
           'flow', 'get_files', 'save_array']

# Cell
import os
import numpy as np
from fastcore.all import *
import zipfile

from typing import Iterable, TypeVar, Generator
from plum import dispatch
from pathlib import Path
from functools import reduce

function = type(lambda: ())
T = TypeVar('T')

# Cell
def identity(x: T) -> T:
    """Indentity function."""

    return x

# Cell
def simplify(x):
    """Return an object of an iterable if it is lonely."""


    @dispatch
    def _simplify(x):
        if callable(x):
            try:
                return x()
            except TypeError:
                pass
        return x

    @dispatch
    def _simplify(i: Iterable): return next(i.__iter__()) if len(i) == 1 else i

    return _simplify(x)

# Cell
def listify(x, *args):
    """Convert `x` to a `list`."""
    if args:
        x = (x,) + args

    if x is None:
        result = []
    elif isinstance(x, list): result = x
    elif isinstance(x, str) or hasattr(x, "__array__") or hasattr(x, "iloc"):
        result = [x]
    elif isinstance(x, (Iterable, Generator)):
        result = list(x)
    else:
        result = [x]

    return result

# Cell
def setify(x, *args):
    """Convert `x` to a `set`."""

    return set(listify(x, *args))

# Cell
def tuplify(x, *args):
    """Convert `x` to a `tuple`."""

    return tuple(listify(x, *args))

# Cell
def merge_tfms(*tfms):
    """Merge two dictionnaries by stacking common key into list."""

    def _merge_tfms(tf1, tf2):
        return {
            k: simplify(listify(setify(listify(tf1.get(k)) + listify(tf2.get(k)))))
            for k in {**tf1, **tf2}
        }

    return reduce(_merge_tfms, tfms, dict())

# Cell
def compose(*functions):
    """Compose an arbitrary number of functions."""

    def _compose(fn1, fn2):
        return lambda x: fn1(fn2(x))

    return reduce(_compose, functions, identity)

# Cell
def pipe(*functions):
    """Pipe an arbitrary number of functions."""

    return compose(*functions[::-1])

# Cell
def flow(data, *functions):
    """Flow `data` through a list of functions."""

    return pipe(*functions)(data)

# Cell
def get_files(path, extensions=None, recurse=False, folders=None, followlinks=True):
    """Get all those file names."""
    path = Path(path)
    folders = listify(folders)
    extensions = setify(extensions)
    extensions = {e.lower() for e in extensions}

    def simple_getter(p, fs, extensions=None):
        p = Path(p)
        res = [
            p / f
            for f in fs
            if not f.startswith(".")
            and ((not extensions) or f'.{f.split(".")[-1].lower()}' in extensions)
        ]
        return res

    if recurse:
        result = []
        for i, (p, d, f) in enumerate(os.walk(path, followlinks=followlinks)):
            if len(folders) != 0 and i == 0:
                d[:] = [o for o in d if o in folders]
            else:
                d[:] = [o for o in d if not o.startswith(".")]
            if len(folders) != 0 and i == 0 and "." not in folders:
                continue
            result += simple_getter(p, f, extensions)
    else:
        f = [o.name for o in os.scandir(path) if o.is_file()]
        result = simple_getter(path, f, extensions)
    return list(map(str, result))

# Cell
from fuzzywuzzy.process import extractOne

@patch
def find(self: Path, match: str):
    """Find the matching element in path according to Levenshtein Distance."""
    return Path(extractOne(match, map(str, self.ls()))[0])

# Cell
@patch
def decompress(self: Path, dest='.'):

    if self.suffix == '.zip':
        with zipfile.ZipFile(self, 'r') as f:
            f.extractall(dest)
    elif self.suffix == 'tar':
        print('tar')
    else:
        raise ValueError('extension of the file is not supported')

# Cell
@patch
def compress(self: Path, dest='.', keep_copy=True):

    return 'I compress.'

# Cell
from fastdownload import FastDownload

@patch
def download(self: Path, url, dest='tmp/'):
    """TODO ça marche pas."""

    FastDownload(base=dest).get(url)

# Cell
def save_array(array, fname, suffix):
    """Save an array with the given name and suffix."""
    if not suffix.startswith("."):
        suffix = "." + suffix

    fname = Path(fname)

    return np.save(array, fname.with_suffix(suffix))