# coding: utf-8
from .autopath import do_autopath
do_autopath()
from .config import config_type, get_config

from py.test import raises

from tiramisu import IntOption, UnicodeOption, OptionDescription, Config
from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.storage import list_sessions, delete_session


def teardown_function(function):
    assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__)


def make_description():
    u1 = IntOption('u1', '', properties=('frozen', 'mandatory', 'disabled', ))
    u2 = IntOption('u2', '', properties=('frozen', 'mandatory', 'disabled', ))
    return OptionDescription('od1', '', [u1, u2])


def test_permissive(config_type):
    descr = make_description()
    cfg_ori = Config(descr)
    cfg_ori.property.read_write()
    cfg_ori.property.read_write()
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.unrestraint.permissive.set(frozenset(['disabled']))
    assert cfg_ori.unrestraint.permissive.get() == frozenset(['disabled'])
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.add('permissive')
    cfg = get_config(cfg_ori, config_type)
    cfg.option('u1').value.get()
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.pop('permissive')
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}


def test_permissive_add(config_type):
    descr = make_description()
    cfg_ori = Config(descr)
    cfg_ori.property.read_write()
    cfg_ori.property.read_write()
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.unrestraint.permissive.add('disabled')
    assert cfg_ori.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.add('permissive')
    cfg = get_config(cfg_ori, config_type)
    cfg.option('u1').value.get()
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.pop('permissive')
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}


def test_permissive_pop():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    cfg.property.read_write()
    props = frozenset()
    try:
        cfg.forcepermissive.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    cfg.unrestraint.permissive.add('disabled')
    assert cfg.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
    cfg.forcepermissive.option('u1').value.get()
    cfg.unrestraint.permissive.pop('disabled')
    props = frozenset()
    try:
        cfg.forcepermissive.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}


def test_permissive_reset():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    assert cfg.unrestraint.permissive.get() == frozenset(['hidden'])
    #
    cfg.unrestraint.permissive.set(frozenset(['disabled']))
    assert cfg.unrestraint.permissive.get() == frozenset(['disabled'])
    #
    cfg.unrestraint.permissive.reset()
    assert cfg.unrestraint.permissive.get() == frozenset()


def test_permissive_mandatory():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_only()
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    cfg.unrestraint.permissive.set(frozenset(['mandatory', 'disabled']))
    assert cfg.unrestraint.permissive.get() == frozenset(['mandatory', 'disabled'])
    cfg.property.add('permissive')
    cfg.option('u1').value.get()
    cfg.property.pop('permissive')
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_permissive_frozen():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    cfg.unrestraint.permissive.set(frozenset(['frozen', 'disabled']))
    assert cfg.unrestraint.permissive.get() == frozenset(['frozen', 'disabled'])
    assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
    try:
        cfg.option('u1').value.set(1)
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    cfg.property.add('permissive')
    cfg.option('u1').value.set(1)
    assert cfg.option('u1').value.get() == 1
    cfg.property.pop('permissive')
    try:
        cfg.option('u1').value.set(1)
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_invalid_permissive():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    raises(TypeError, "cfg.unrestraint.permissive.set(['frozen', 'disabled'])")


def test_forbidden_permissive():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    raises(ConfigError, "cfg.permissive.set(frozenset(['force_default_on_freeze']))")
    raises(ConfigError, "cfg.permissive.set(frozenset(['force_metaconfig_on_freeze']))")


def test_permissive_option(config_type):
    descr = make_description()
    cfg_ori = Config(descr)
    cfg_ori.property.read_write()
    cfg = get_config(cfg_ori, config_type)

    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.add('permissive')
    cfg = get_config(cfg_ori, config_type)
    cfg.option('u1').value.get()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.property.pop('permissive')
    cfg = get_config(cfg_ori, config_type)
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}


def test_permissive_option_cache():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()

    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    cfg.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    cfg.property.add('permissive')
    cfg.option('u1').value.get()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}

    cfg.property.pop('permissive')
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset()
    props = frozenset()
    try:
        cfg.option('u2').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert set(props) == {'disabled'}


def test_permissive_option_mandatory():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_only()
    props = frozenset()
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])
    cfg.unrestraint.option('u1').permissive.set(frozenset(['mandatory', 'disabled']))
    assert cfg.unrestraint.option('u1').permissive.get() == frozenset(['mandatory', 'disabled'])
    cfg.property.add('permissive')
    cfg.option('u1').value.get()
    cfg.property.pop('permissive')
    try:
        cfg.option('u1').value.get()
    except PropertiesOptionError as err:
        props = err.proptype
    assert frozenset(props) == frozenset(['disabled'])


def test_permissive_option_frozen():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    cfg.unrestraint.option('u1').permissive.set(frozenset(['frozen', 'disabled']))
    cfg.option('u1').value.set(1)
    assert cfg.option('u1').value.get() == 1
    cfg.property.add('permissive')
    assert cfg.option('u1').value.get() == 1
    cfg.property.pop('permissive')
    assert cfg.option('u1').value.get() == 1


def test_invalid_option_permissive():
    descr = make_description()
    cfg = Config(descr)
    cfg.property.read_write()
    raises(TypeError, "cfg.unrestraint.option('u1').permissive.set(['frozen', 'disabled'])")


def test_remove_option_permissive(config_type):
    var1 = UnicodeOption('var1', '', u'value', properties=('hidden',))
    od1 = OptionDescription('od1', '', [var1])
    rootod = OptionDescription('rootod', '', [od1])
    cfg_ori = Config(rootod)
    cfg_ori.property.read_write()
    cfg = get_config(cfg_ori, config_type)
    raises(PropertiesOptionError, "cfg.option('od1.var1').value.get()")
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
    assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
    cfg = get_config(cfg_ori, config_type)
    assert cfg.option('od1.var1').value.get() == 'value'
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset())
    assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset()
    cfg = get_config(cfg_ori, config_type)
    raises(PropertiesOptionError, "cfg.option('od1.var1').value.get()")


def test_reset_option_permissive(config_type):
    var1 = UnicodeOption('var1', '', u'value', properties=('hidden',))
    od1 = OptionDescription('od1', '', [var1])
    rootod = OptionDescription('rootod', '', [od1])
    cfg_ori = Config(rootod)
    cfg_ori.property.read_write()
    cfg = get_config(cfg_ori, config_type)
    raises(PropertiesOptionError, "cfg.option('od1.var1').value.get()")
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
    assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
    cfg = get_config(cfg_ori, config_type)
    assert cfg.option('od1.var1').value.get() == 'value'
    if config_type == 'tiramisu-api':
        cfg.send()
    cfg_ori.forcepermissive.option('od1.var1').permissive.reset()
    assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset()
    cfg = get_config(cfg_ori, config_type)
    raises(PropertiesOptionError, "cfg.option('od1.var1').value.get()")