from __future__ import print_function

import sys
from os import listdir, path as osp

from six import text_type, binary_type, PY3

from cubicweb import Binary


def fsimport(cw, fspaths, parenteid=None, mapfolders=True, bfss=False,
             fsencoding=sys.stdout.encoding or 'utf-8', quiet=False):
    assert bfss, 'not implemented'
    if bfss:
        cw.transaction_data['fs_importing'] = True
    if parenteid is not None:
        parent = cw.execute('Any X WHERE X eid %(x)s',
                            {'x': parenteid}).get_entity(0, 0)
    else:
        parent = None
    # XXX what if not bfss?
    alreadyimported = set(x.getvalue() for x, in cw.execute(
        'Any fspath(D) WHERE X data D, X is File'))
    for fspath in fspaths:
        fspath = osp.abspath(osp.normpath(fspath))
        if osp.isdir(fspath):
            import_directory(cw, fspath, parent, mapfolders, bfss, fsencoding,
                             quiet, _alreadyimported=alreadyimported)
        else:
            import_file(cw, fspath, parent, bfss, fsencoding, quiet,
                        _alreadyimported=alreadyimported)


def import_directory(cw, directory, parent=None, mapfolders=True, bfss=False,
                     fsencoding=sys.stdout.encoding or 'utf-8', quiet=False,
                     _indent='', _alreadyimported=None):
    if _alreadyimported is None:
        _alreadyimported = set()
    # getting directory content will check it's validity, do it before creating
    # any Folder entity
    dirfiles = listdir(directory)
    # XXX what if not bfss
    if mapfolders:
        parent = folder_entity(cw, directory, parent=parent,
                               fsencoding=fsencoding)
    if not quiet:
        print(_indent + '** importing directory', directory)
    for fname in dirfiles:
        fspath = osp.join(directory, fname)
        if osp.isdir(fspath):
            import_directory(cw, fspath, parent, mapfolders, bfss, fsencoding,
                             quiet, _indent=_indent + '  ',
                             _alreadyimported=_alreadyimported)
        else:
            import_file(cw, fspath, parent, bfss, fsencoding, quiet,
                        _indent=_indent + '  ',
                        _alreadyimported=_alreadyimported)


def import_file(cw, fspath, parent=None, bfss=False,
                fsencoding=sys.stdout.encoding or 'utf-8', quiet=False,
                _indent='', _alreadyimported=None):
    fname = osp.basename(fspath)
    if isinstance(fname, binary_type):
        fname = fname.decode(fsencoding)
    if PY3 and isinstance(fspath, text_type):
        fspath = fspath.encode(fsencoding)
    if _alreadyimported is None:
        _alreadyimported = set()
    if fspath in _alreadyimported:
        if not quiet:
            print(_indent + '  skipping already imported', fname)
        return
    if not quiet:
        print(_indent + '  importing', fname)
    if bfss:
        efile = cw.create_entity('File', data_name=fname,
                                 data=Binary(fspath))
    else:
        with open(fspath, 'rb') as stream:
            efile = cw.create_entity('File', data_name=fname,
                                     data=Binary(stream.read()))
    _alreadyimported.add(fspath)
    if parent is not None:
        efile.cw_set(filed_under=parent)


def folder_entity(cw, directory, parent=None, fsencoding='utf-8'):
    if isinstance(directory, binary_type):
        directory = directory.decode(fsencoding)
    if parent is None:
        rset = cw.execute('Folder X WHERE X name %(name)s',
                          {'name': directory})
    else:
        rset = cw.execute('Folder X WHERE X name %(name)s, '
                          'X filed_under P, P eid %(p)s',
                          {'name': osp.dirname(directory), 'p': parent.eid})
    if rset:
        return rset.get_entity(0, 0)
    # create the folder
    if parent is None:
        return cw.create_entity('Folder', name=directory)
    return cw.create_entity('Folder', name=directory, filed_under=parent)
