# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
"""Check the resolving/rebasing feature of ``BasePath``s."""
from __future__ import print_function, unicode_literals

from ... import base as nib
from ..traits_extension import rebase_path_traits, resolve_path_traits, Path


class _test_spec(nib.TraitedSpec):
    a = nib.File()
    b = nib.traits.Tuple(nib.File(), nib.File())
    c = nib.traits.List(nib.File())
    d = nib.traits.Either(nib.File(), nib.traits.Float())
    e = nib.OutputMultiObject(nib.File())
    ee = nib.OutputMultiObject(nib.Str)
    f = nib.traits.Dict(nib.Str, nib.File())
    g = nib.traits.Either(nib.File, nib.Str)
    h = nib.Str
    i = nib.traits.Either(nib.File, nib.traits.Tuple(nib.File, nib.traits.Int))
    j = nib.traits.Either(nib.File, nib.traits.Tuple(nib.File, nib.traits.Int),
                          nib.traits.Dict(nib.Str, nib.File()))
    k = nib.DictStrStr


def test_rebase_resolve_path_traits():
    """Check rebase_path_traits and resolve_path_traits and idempotence."""
    spec = _test_spec()

    v = '/some/path/f1.txt'
    a = rebase_path_traits(spec.trait('a'), v, '/some/path')
    assert a == Path('f1.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('a'), a, '/some/path') == a

    a = resolve_path_traits(spec.trait('a'), a, '/some/path')
    assert a == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('a'), a, '/some/path') == a

    a = rebase_path_traits(spec.trait('a'), v, '/some/other/path')
    assert a == Path(v)

    # Idempotence
    assert rebase_path_traits(spec.trait('a'), a, '/some/other/path') == a

    a = resolve_path_traits(spec.trait('a'), a, '/some/path')
    assert a == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('a'), a, '/some/path') == a

    v = ('/some/path/f1.txt', '/some/path/f2.txt')
    b = rebase_path_traits(spec.trait('b'), v, '/some/path')
    assert b == (Path('f1.txt'), Path('f2.txt'))

    # Idempotence
    assert rebase_path_traits(spec.trait('b'), b, '/some/path') == b

    b = resolve_path_traits(spec.trait('b'), b, '/some/path')
    assert b == (Path(v[0]), Path(v[1]))

    # Idempotence
    assert resolve_path_traits(spec.trait('b'), b, '/some/path') == b

    v = ['/some/path/f1.txt', '/some/path/f2.txt', '/some/path/f3.txt']
    c = rebase_path_traits(spec.trait('c'), v, '/some/path')
    assert c == [Path('f1.txt'), Path('f2.txt'), Path('f3.txt')]

    # Idempotence
    assert rebase_path_traits(spec.trait('c'), c, '/some/path') == c

    c = resolve_path_traits(spec.trait('c'), c, '/some/path')
    assert c == [Path(vp) for vp in v]

    # Idempotence
    assert resolve_path_traits(spec.trait('c'), c, '/some/path') == c

    v = 2.0
    d = rebase_path_traits(spec.trait('d'), v, '/some/path')
    assert d == v

    d = resolve_path_traits(spec.trait('d'), d, '/some/path')
    assert d == v

    v = '/some/path/either.txt'
    d = rebase_path_traits(spec.trait('d'), v, '/some/path')
    assert d == Path('either.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('d'), d, '/some/path') == d

    d = resolve_path_traits(spec.trait('d'), d, '/some/path')
    assert d == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('d'), d, '/some/path') == d

    v = ['/some/path/f1.txt', '/some/path/f2.txt', '/some/path/f3.txt']
    e = rebase_path_traits(spec.trait('e'), v, '/some/path')
    assert e == [Path('f1.txt'), Path('f2.txt'), Path('f3.txt')]

    # Idempotence
    assert rebase_path_traits(spec.trait('e'), e, '/some/path') == e

    e = resolve_path_traits(spec.trait('e'), e, '/some/path')
    assert e == [Path(vp) for vp in v]

    # Idempotence
    assert resolve_path_traits(spec.trait('e'), e, '/some/path') == e

    v = [['/some/path/f1.txt', '/some/path/f2.txt'], [['/some/path/f3.txt']]]
    e = rebase_path_traits(spec.trait('e'), v, '/some/path')
    assert e == [[Path('f1.txt'), Path('f2.txt')], [[Path('f3.txt')]]]

    # Idempotence
    assert rebase_path_traits(spec.trait('e'), e, '/some/path') == e

    e = resolve_path_traits(spec.trait('e'), e, '/some/path')
    assert e == [[[Path(vpp) for vpp in vp] if isinstance(vp, list) else Path(vp) for vp in inner]
                 for inner in v]

    # Idempotence
    assert resolve_path_traits(spec.trait('e'), e, '/some/path') == e

    # These are Str - no rebasing/resolving should happen
    v = [['/some/path/f1.txt', '/some/path/f2.txt'], [['/some/path/f3.txt']]]
    ee = rebase_path_traits(spec.trait('ee'), v, '/some/path')
    assert ee == v

    # Idempotence
    assert rebase_path_traits(spec.trait('ee'), ee, '/some/path') == ee

    ee = resolve_path_traits(spec.trait('ee'), [['f1.txt', 'f2.txt'], [['f3.txt']]], '/some/path')
    assert ee == [['f1.txt', 'f2.txt'], [['f3.txt']]]

    # Idempotence
    assert resolve_path_traits(spec.trait('ee'), ee, '/some/path') == ee

    v = {'1': '/some/path/f1.txt'}
    f = rebase_path_traits(spec.trait('f'), v, '/some')
    assert f == {'1': Path('path/f1.txt')}

    # Idempotence
    assert rebase_path_traits(spec.trait('f'), f, '/some') == f

    f = resolve_path_traits(spec.trait('f'), f, '/some')
    assert f == {k: Path(val) for k, val in v.items()}

    # Idempotence
    assert resolve_path_traits(spec.trait('f'), f, '/some') == f

    # Either(Str, File): passing in path-like apply manipulation
    v = '/some/path/either.txt'
    g = rebase_path_traits(spec.trait('g'), v, '/some/path')
    assert g == Path('either.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('g'), g, '/some/path') == g

    g = resolve_path_traits(spec.trait('g'), g, '/some/path')
    assert g == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('g'), g, '/some/path') == g

    g = rebase_path_traits(spec.trait('g'), v, '/some')
    assert g == Path('path/either.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('g'), g, '/some/path') == g

    g = resolve_path_traits(spec.trait('g'), g, '/some')
    assert g == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('g'), g, '/some/path') == g

    # Either(Str, File): passing str discards File
    v = 'either.txt'
    g = rebase_path_traits(spec.trait('g'), v, '/some/path')
    assert g == v

    # Idempotence
    assert rebase_path_traits(spec.trait('g'), g, '/some/path') == g

    # This is a problematic case, it is impossible to know whether this
    # was meant to be a string or a file.
    # In this implementation, strings take precedence
    g = resolve_path_traits(spec.trait('g'), g, '/some/path')
    assert g == v

    # Idempotence
    assert resolve_path_traits(spec.trait('g'), g, '/some/path') == g

    v = 'string'
    g = rebase_path_traits(spec.trait('g'), v, '/some')
    assert g == v

    # Idempotence
    assert rebase_path_traits(spec.trait('g'), g, '/some') == g

    # This is a problematic case, it is impossible to know whether this
    # was meant to be a string or a file.
    g = resolve_path_traits(spec.trait('g'), v, '/some')
    assert g == v

    # Idempotence
    assert resolve_path_traits(spec.trait('g'), g, '/some') == g

    g = rebase_path_traits(spec.trait('g'), v, '/some/path')
    assert g == v  # You dont want this one to be a Path

    # Idempotence
    assert rebase_path_traits(spec.trait('g'), g, '/some/path') == g

    # This is a problematic case, it is impossible to know whether this
    # was meant to be a string or a file.
    g = resolve_path_traits(spec.trait('g'), g, '/some/path')
    assert g == v  # You dont want this one to be a Path

    # Idempotence
    assert resolve_path_traits(spec.trait('g'), g, '/some/path') == g

    h = rebase_path_traits(spec.trait('h'), v, '/some/path')
    assert h == v

    # Idempotence
    assert rebase_path_traits(spec.trait('h'), h, '/some/path') == h

    h = resolve_path_traits(spec.trait('h'), h, '/some/path')
    assert h == v

    # Idempotence
    assert resolve_path_traits(spec.trait('h'), h, '/some/path') == h

    v = '/some/path/either/file.txt'
    i = rebase_path_traits(spec.trait('i'), v, '/some/path')
    assert i == Path('either/file.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('i'), i, '/some/path') == i

    i = resolve_path_traits(spec.trait('i'), i, '/some/path')
    assert i == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('i'), i, '/some/path') == i

    v = ('/some/path/either/tuple/file.txt', 2)
    i = rebase_path_traits(spec.trait('i'), v, '/some/path')
    assert i == (Path('either/tuple/file.txt'), 2)

    # Idempotence
    assert rebase_path_traits(spec.trait('i'), i, '/some/path') == i

    i = resolve_path_traits(spec.trait('i'), i, '/some/path')
    assert i == (Path(v[0]), v[1])

    # Idempotence
    assert resolve_path_traits(spec.trait('i'), i, '/some/path') == i

    v = '/some/path/either/file.txt'
    j = rebase_path_traits(spec.trait('j'), v, '/some/path')
    assert j == Path('either/file.txt')

    # Idempotence
    assert rebase_path_traits(spec.trait('j'), j, '/some/path') == j

    j = resolve_path_traits(spec.trait('j'), j, '/some/path')
    assert j == Path(v)

    # Idempotence
    assert resolve_path_traits(spec.trait('j'), j, '/some/path') == j

    v = ('/some/path/either/tuple/file.txt', 2)
    j = rebase_path_traits(spec.trait('j'), ('/some/path/either/tuple/file.txt', 2), '/some/path')
    assert j == (Path('either/tuple/file.txt'), 2)

    # Idempotence
    assert rebase_path_traits(spec.trait('j'), j, '/some/path') == j

    j = resolve_path_traits(spec.trait('j'), j, '/some/path')
    assert j == (Path(v[0]), v[1])

    # Idempotence
    assert resolve_path_traits(spec.trait('j'), j, '/some/path') == j

    v = {'a': '/some/path/either/dict/file.txt'}
    j = rebase_path_traits(spec.trait('j'), v, '/some/path')
    assert j == {'a': Path('either/dict/file.txt')}

    # Idempotence
    assert rebase_path_traits(spec.trait('j'), j, '/some/path') == j

    j = resolve_path_traits(spec.trait('j'), j, '/some/path')
    assert j == {k: Path(val) for k, val in v.items()}

    # Idempotence
    assert resolve_path_traits(spec.trait('j'), j, '/some/path') == j

    v = {'path': '/some/path/f1.txt'}
    k = rebase_path_traits(spec.trait('k'), v, '/some/path')
    assert k == v

    # Idempotence
    assert rebase_path_traits(spec.trait('k'), k, '/some/path') == k

    k = resolve_path_traits(spec.trait('k'), k, '/some/path')
    assert k == v
