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

from py.test import raises
from tiramisu.config import Config
from tiramisu.option import StrOption, UnicodeOption, OptionDescription
from tiramisu.error import PropertiesOptionError
from tiramisu.setting import groups


def make_description():
    stroption = StrOption('str', 'Test string option', default="abc",
                          properties=('mandatory', ))
    stroption1 = StrOption('str1', 'Test string option',
                           properties=('mandatory', ))
    stroption2 = UnicodeOption('unicode2', 'Test string option',
                               properties=('mandatory', ))
    stroption3 = StrOption('str3', 'Test string option', multi=True,
                           properties=('mandatory', ))
    stroption4 = StrOption('str4', 'Test string option', multi=True,
                           properties=('mandatory', ), allow_empty_list=True)
    descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, stroption4])
    return descr


def test_mandatory_ro():
    descr = make_description()
    config = Config(descr)
    config.read_only()
    prop = []
    try:
        config.str1
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop
    config.read_write()
    config.str1 = 'yes'
    config.read_only()
    assert config.str1 == 'yes'


def test_mandatory_rw():
    descr = make_description()
    config = Config(descr)
    config.read_write()
    #not mandatory in rw
    config.str1
    config.str1 = 'yes'
    assert config.str1 == 'yes'


def test_mandatory_default():
    descr = make_description()
    config = Config(descr)
    config.read_only()
    #not mandatory in rw
    config.str
    config.read_write()
    config.str = 'yes'
    config.read_only()
    config.str
    config.read_write()
    config.str = None
    config.read_only()
    prop = []
    try:
        config.str
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


#valeur vide : None, '', u'', ...
def test_mandatory_none():
    descr = make_description()
    config = Config(descr)
    config.str1 = None
    assert config.getowner(config.unwrap_from_path('str1')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str1
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


def test_mandatory_empty():
    descr = make_description()
    config = Config(descr)
    config.str1 = ''
    assert config.getowner(config.unwrap_from_path('str1')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str1
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


def test_mandatory_multi_none():
    descr = make_description()
    config = Config(descr)
    config.str3 = [None]
    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str3
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop
    config.read_write()
    config.str3 = ['yes', None]
    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str3
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


def test_mandatory_multi_empty():
    descr = make_description()
    config = Config(descr)
    config.str3 = []
    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str3
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop
    #
    config.read_write()
    config.str3 = ['']
    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str3
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop
    #
    config.read_write()
    config.str3 = ['yes', '']
    assert config.getowner(config.unwrap_from_path('str3')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str3
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


def test_mandatory_multi_empty_allow_empty_list():
    descr = make_description()
    config = Config(descr)
    config.str4 = []
    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
    config.read_only()
    prop = []
    config.str4
    #
    config.read_write()
    config.str4 = ['']
    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str4
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop
    #
    config.read_write()
    config.str4 = ['yes', '']
    assert config.getowner(config.unwrap_from_path('str4')) == 'user'
    config.read_only()
    prop = []
    try:
        config.str4
    except PropertiesOptionError as err:
        prop = err.proptype
    assert 'mandatory' in prop


def test_mandatory_multi_append():
    descr = make_description()
    config = Config(descr)
    config.str3 = ['yes']
    config.read_write()
    config.str3.append(None)


def test_mandatory_disabled():
    descr = make_description()
    config = Config(descr)
    setting = config.cfgimpl_get_settings()
    config.str1
    config.read_only()
    prop = []
    try:
        config.str1
    except PropertiesOptionError as err:
        prop = err.proptype
    assert prop == ['mandatory']
    setting[descr.str1].append('disabled')
    prop = []
    try:
        config.str1
    except PropertiesOptionError as err:
        prop = err.proptype
    assert set(prop) == set(['disabled', 'mandatory'])


def test_mandatory_unicode():
    descr = make_description()
    config = Config(descr)
    config.unicode2
    config.read_only()
    prop = []
    try:
        config.unicode2
    except PropertiesOptionError as err:
        prop = err.proptype
    assert prop == ['mandatory']
    config.read_write()
    config.unicode2 = u''
    config.read_only()
    prop = []
    try:
        config.unicode2
    except PropertiesOptionError as err:
        prop = err.proptype
    assert prop == ['mandatory']


def test_mandatory_warnings_ro():
    descr = make_description()
    config = Config(descr)
    config.str = ''
    config.read_only()
    proc = []
    try:
        config.str
    except PropertiesOptionError as err:
        proc = err.proptype
    assert proc == ['mandatory']
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
    config.read_write()
    config.str = 'a'
    config.read_only()
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
    assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
    sleep(.1)


def test_mandatory_warnings_rw():
    descr = make_description()
    config = Config(descr)
    config.str = ''
    config.read_write()
    config.str
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
    config.str = 'a'
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
    assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
    sleep(.1)


def test_mandatory_warnings_disabled():
    descr = make_description()
    config = Config(descr)
    config.str = ''
    setting = config.cfgimpl_get_settings()
    config.read_write()
    config.str
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
    setting[descr.str].append('disabled')
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
    assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str1', 'unicode2', 'str3']
    sleep(.1)


def test_mandatory_warnings_hidden():
    descr = make_description()
    config = Config(descr)
    config.str = ''
    setting = config.cfgimpl_get_settings()
    config.read_write()
    config.cfgimpl_get_settings().setpermissive(('hidden',))
    config.str
    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
    setting[descr.str].append('hidden')
    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
    assert list(config.cfgimpl_get_values().mandatory_warnings(force_permissive=True)) == ['str', 'str1', 'unicode2', 'str3']


def test_mandatory_warnings_frozen():
    descr = make_description()
    config = Config(descr)
    config.str = ''
    setting = config.cfgimpl_get_settings()
    config.read_write()
    config.str
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
    setting[descr.str].append('frozen')
    config.read_only()
    assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
    sleep(.1)


def test_mandatory_master():
    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True,
                              properties=('mandatory', ))
    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
                                   multi=True)
    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    interface1.impl_set_group_type(groups.master)
    o = OptionDescription('o', '', [interface1])
    config = Config(o)
    config.read_only()
    raises(PropertiesOptionError, 'config.ip_admin_eth0.ip_admin_eth0')
    raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0')


def test_mandatory_master_empty():
    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 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    interface1.impl_set_group_type(groups.master)
    o = OptionDescription('o', '', [interface1])
    config = Config(o)
    config.read_write()
    assert config.ip_admin_eth0.ip_admin_eth0 == []
    assert config.ip_admin_eth0.netmask_admin_eth0 == []
    #
    config.ip_admin_eth0.ip_admin_eth0.append()
    assert config.ip_admin_eth0.ip_admin_eth0 == [None]
    assert config.ip_admin_eth0.netmask_admin_eth0 == [None]
    config.read_only()
    raises(PropertiesOptionError, "config.ip_admin_eth0.ip_admin_eth0")
    raises(PropertiesOptionError, "config.ip_admin_eth0.netmask_admin_eth0")
    config.read_write()
    del(config.ip_admin_eth0.ip_admin_eth0)
    del(config.ip_admin_eth0.netmask_admin_eth0)
    assert config.ip_admin_eth0.ip_admin_eth0 == []
    assert config.ip_admin_eth0.netmask_admin_eth0 == []
    #
    config.ip_admin_eth0.ip_admin_eth0.append('')
    assert config.ip_admin_eth0.ip_admin_eth0 == ['']
    assert config.ip_admin_eth0.netmask_admin_eth0 == [None]
    config.read_only()
    raises(PropertiesOptionError, "config.ip_admin_eth0.ip_admin_eth0")
    raises(PropertiesOptionError, "config.ip_admin_eth0.netmask_admin_eth0")
    config.read_write()
    #
    config.read_write()
    config.ip_admin_eth0.ip_admin_eth0 = ['ip']
    config.read_only()
    assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
    assert config.ip_admin_eth0.netmask_admin_eth0 == [None]


def test_mandatory_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, properties=('mandatory', ))
    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
    interface1.impl_set_group_type(groups.master)
    o = OptionDescription('o', '', [interface1])
    config = Config(o)
    config.read_only()
    assert config.ip_admin_eth0.ip_admin_eth0 == []
    assert config.ip_admin_eth0.netmask_admin_eth0 == []
    #
    config.read_write()
    config.ip_admin_eth0.ip_admin_eth0.append('ip')
    config.read_only()
    assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
    raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0')
    #
    config.read_write()
    config.ip_admin_eth0.netmask_admin_eth0 = ['']
    config.read_only()
    assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
    raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0')
    #
    config.read_write()
    config.ip_admin_eth0.netmask_admin_eth0 = ['ip']
    config.read_only()
    assert config.ip_admin_eth0.ip_admin_eth0 == ['ip']
    assert config.ip_admin_eth0.netmask_admin_eth0 == ['ip']