# coding: utf-8
from .autopath import do_autopath
do_autopath()

from tiramisu import BoolOption, StrOption, SymLinkOption, \
    OptionDescription, MasterSlaves, Config
from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import groups, owners
from tiramisu.api import TIRAMISU_VERSION

from py.test import raises


def return_value():
    pass


#____________________________________________________________
def test_symlink_option():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    assert api.option('s1.b').value.get() is False
    api.option("s1.b").value.set(True)
    api.option("s1.b").value.set(False)
    assert api.option('s1.b').value.get() is False
    assert api.option('c').value.get() is False
    api.option('s1.b').value.set(True)
    assert api.option('s1.b').value.get() is True
    assert api.option('c').value.get() is True
    api.option('s1.b').value.set(False)
    assert api.option('s1.b').value.get() is False
    assert api.option('c').value.get() is False


def test_symlink_assign_option():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    raises(ConfigError, "api.option('c').value.set(True)")


def test_symlink_del_option():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    raises(TypeError, "api.option('c').value.reset()")


def test_symlink_addproperties():
    boolopt = BoolOption('b', '', default=True, properties=('test',))
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription('opt', '', [boolopt, linkopt])
    api = Config(descr)
    api.property.read_write()
    raises(TypeError, "api.option('c').property.add('new')")
    raises(TypeError, "api.option('c').property.reset()")


def test_symlink_addpermissive():
    boolopt = BoolOption('b', '', default=True, properties=('test',))
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription('opt', '', [boolopt, linkopt])
    api = Config(descr)
    api.property.read_write()
    raises(TypeError, "api.option('c').permissive.set(frozenset(['new']))")
    raises(TypeError, "api.option('c').permissive.reset()")


def test_symlink_getproperties():
    boolopt = BoolOption('b', '', default=True, properties=('test',))
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription('opt', '', [boolopt, linkopt])
    api = Config(descr)
    api.property.read_write()
    if TIRAMISU_VERSION == 2:
        assert boolopt.impl_getproperties() == linkopt.impl_getproperties() == ('test',)
    else:
        assert boolopt.impl_getproperties() == linkopt.impl_getproperties() == {'test'}
    assert boolopt.impl_has_callback() == linkopt.impl_has_callback() == False


def test_symlink_getcallback():
    boolopt = BoolOption('b', '', callback=return_value)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription('opt', '', [boolopt, linkopt])
    api = Config(descr)
    api.property.read_write()
    assert boolopt.impl_has_callback() == linkopt.impl_has_callback() == True
    assert boolopt.impl_get_callback() == linkopt.impl_get_callback() == (return_value, None)


def test_symlink_requires():
    boolopt = BoolOption('b', '', default=True)
    stropt = StrOption('s', '', requires=[{'option': boolopt,
                                           'expected': False,
                                           'action': 'disabled'}])
    linkopt = SymLinkOption("c", stropt)
    descr = OptionDescription('opt', '', [boolopt, stropt, linkopt])
    api = Config(descr)
    api.property.read_write()
    assert api.option('b').value.get() is True
    assert api.option('s').value.get() is None
    assert api.option('c').value.get() is None
    api.option('b').value.set(False)
    #
    props = []
    try:
        api.option('s').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    if TIRAMISU_VERSION == 2:
        assert props == ['disabled']
    else:
        assert props == {'disabled'}
    #
    props = []
    try:
        api.option('c').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    if TIRAMISU_VERSION == 2:
        assert props == ['disabled']
    else:
        assert props == {'disabled'}


def test_symlink_multi():
    boolopt = BoolOption("b", "", default=[False], multi=True)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    assert api.option('s1.b').value.get() == [False]
    assert api.option('c').value.get() == [False]
    api.option('s1.b').value.set([True])
    assert api.option('s1.b').value.get() == [True]
    assert api.option('c').value.get() == [True]
    api.option('s1.b').value.set([False])
    assert api.option('s1.b').value.get() == [False]
    assert api.option('c').value.get() == [False]
    api.option('s1.b').value.set([False, True])
    assert api.option('s1.b').value.get() == [False, True]
    assert api.option('c').value.get() == [False, True]
    assert boolopt.impl_is_multi() is True
    assert linkopt.impl_is_multi() is True


def test_symlink_assign():
    if TIRAMISU_VERSION != 2:
        boolopt = BoolOption("b", "", default=False)
        linkopt = SymLinkOption("c", boolopt)
        descr = OptionDescription("opt", "",
                                  [linkopt, OptionDescription("s1", "", [boolopt])])
        api = Config(descr)
        raises(ConfigError, "api.option('c').value.set(True)")


def test_symlink_owner():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    assert api.option('s1.b').owner.isdefault()
    assert api.option('c').owner.isdefault()
    api.option('s1.b').value.set(True)
    assert not api.option('s1.b').owner.isdefault()
    assert not api.option('c').owner.isdefault()


def test_symlink_get_information():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    boolopt.impl_set_information('test', 'test')
    assert boolopt.impl_get_information('test') == 'test'
    assert linkopt.impl_get_information('test') == 'test'
    boolopt.impl_set_information('test', 'test2')
    assert boolopt.impl_get_information('test') == 'test2'
    assert linkopt.impl_get_information('test') == 'test2'


def test_symlink_master():
    a = StrOption('a', "", multi=True)
    ip_admin_eth0 = SymLinkOption('ip_admin_eth0', a)
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "", multi=True)
    raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")


def test_symlink_slaves():
    a = StrOption('a', "", multi=True)
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
    netmask_admin_eth0 = SymLinkOption('netmask_admin_eth0', a)
    raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")


def test_symlink_with_master():
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
    interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    master = SymLinkOption('master', ip_admin_eth0)
    od = OptionDescription('root', '', [interface1, master])
    api = Config(od)
    assert api.option.make_dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_admin_eth0': [], 'master': []}
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
    assert api.option.make_dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None], 'master': ['val1', 'val2']}


def test_symlink_with_slave():
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
    interface1 = MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    slave = SymLinkOption('slave', netmask_admin_eth0)
    od = OptionDescription('root', '', [interface1, slave])
    api = Config(od)
    assert api.option.make_dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_admin_eth0': [], 'slave': []}
    api.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
    assert api.option.make_dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None], 'slave': [None, None]}
    #
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == None
    assert api.option('slave', 0).value.get() == None
    assert api.option('slave', 1).value.get() == None
    #
    api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val3')
    assert api.option.make_dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, 'val3'], 'slave': [None, 'val3']}
    #
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None
    assert api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val3'
    assert api.option('slave', 0).value.get() == None
    assert api.option('slave', 1).value.get() == 'val3'


#____________________________________________________________
def test_symlink_dependency():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    assert api.option('s1.b').option.has_dependency() is False
    assert api.option('c').option.has_dependency() is True
    assert api.option('s1.b').option.has_dependency(False) is True
    assert api.option('c').option.has_dependency(False) is False

def test_symlink_makedict():
    boolopt = BoolOption("b", "", default=False)
    linkopt = SymLinkOption("c", boolopt)
    descr = OptionDescription("opt", "",
                              [linkopt, OptionDescription("s1", "", [boolopt])])
    api = Config(descr)
    assert api.option.make_dict() == {'c': False, 's1.b': False}
    api.option('s1.b').value.set(True)
    assert api.option.make_dict() == {'c': True, 's1.b': True}