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

from py.test import raises

from tiramisu.error import ConfigError
from tiramisu import Config, BoolOption, OptionDescription, Leadership, \
                     list_sessions, delete_session, default_storage, MetaConfig
from tiramisu.setting import groups, owners


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


def test_non_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    Config(o, session_id='test_non_persistent')


def test_list():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o, session_id='test_non_persistent')
    c.option('b').value.set(True)
    assert 'test_non_persistent' in list_sessions()
    del(c)
    assert 'test_non_persistent' not in list_sessions()


def test_delete_not_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if not default_storage.is_persistent():
        c = Config(o, session_id='not_test_persistent')
        assert 'not_test_persistent' in list_sessions()
        del c
        assert 'not_test_persistent' not in list_sessions()
        #
        c = Config(o, session_id='not_test_persistent')
        raises(ValueError, "delete_session('not_test_persistent')")


def test_create_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        Config(o, session_id='test_persistent', persistent=True)
        delete_session('test_persistent')


def test_create_delete_not_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if not default_storage.is_persistent():
        raises(ValueError, "delete_session('test_persistent')")


def test_list_sessions_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.option('b').value.set(True)
        assert 'test_persistent' in list_sessions()
        delete_session('test_persistent')


def test_delete_session_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        Config(o, session_id='test_persistent', persistent=True)
        assert 'test_persistent' in list_sessions()
        delete_session('test_persistent')
        assert 'test_persistent' not in list_sessions()


def test_create_persistent_retrieve():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.option('b').value.get() is None
        c.option('b').value.set(True)
        assert c.option('b').value.get() is True
        del c
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.option('b').value.get() is True
        assert 'test_persistent' in list_sessions()
        delete_session(c.config.name())
        del c
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.option('b').value.get() is None
        delete_session(c.config.name())
        del c


def test_two_persistent():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c2 = Config(o, session_id='test_persistent', persistent=True)
        c2.property.pop('cache')
        assert c.option('b').value.get() is None
        assert c2.option('b').value.get() is None
        #
        c.option('b').value.set(False)
        assert c.option('b').value.get() is False
        assert c2.option('b').value.get() is False
        #
        c.option('b').value.set(True)
        assert c.option('b').value.get() is True
        assert c2.option('b').value.get() is True
        delete_session('test_persistent')


def test_create_persistent_retrieve_owner():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.option('b').owner.isdefault()
        c.option('b').value.set(True)
        assert c.option('b').value.get()
        assert c.option('b').owner.get() == 'user'
        ##owners.addowner('persistentowner')
        c.option('b').owner.set('persistentowner')
        assert c.option('b').owner.get() == 'persistentowner'
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        c.option('b').owner.set('persistentowner')
        delete_session(c.config.name())
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.option('b').value.get() is None
        assert c.option('b').owner.isdefault()
        delete_session(c.config.name())
        del c


def test_create_persistent_retrieve_owner_leadership():
    a = BoolOption('a', '', multi=True)
    b = BoolOption('b', '', multi=True)
    o = Leadership('a', '', [a, b])
    o1 = OptionDescription('a', '', [o])
    if default_storage.is_persistent():
        c = Config(o1, session_id='test_persistent', persistent=True)
        assert c.option('a.a').owner.isdefault()
        c.option('a.a').value.set([True, False])
        c.option('a.b', 1).value.set(True)
        assert c.option('a.a').owner.get() == 'user'
        assert c.option('a.b', 0).owner.isdefault()
        assert c.option('a.b', 1).owner.get() == 'user'
        #owners.addowner('persistentowner2')
        c.option('a.b', 1).owner.set('persistentowner2')
        c.option('a.b', 0).value.set(True)
        assert c.option('a.b', 0).owner.get() == 'user'
        assert c.option('a.b', 1).owner.get() == 'persistentowner2'
        assert c.option('a.a').value.get() == [True, False]
        del c
        #
        c = Config(o1, session_id='test_persistent', persistent=True)
        assert c.option('a.a').value.get() == [True, False]
        assert c.option('a.b', 0).owner.get() == 'user'
        assert c.option('a.b', 1).owner.get() == 'persistentowner2'
        delete_session(c.config.name())
        del c
        #
        c = Config(o1, session_id='test_persistent', persistent=True)
        assert c.option('a.a').value.get() == []
        delete_session(c.config.name())
        del c


def test_two_persistent_owner():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.property.pop('cache')
        c2 = Config(o, session_id='test_persistent', persistent=True)
        c2.property.pop('cache')
        assert c.option('b').owner.isdefault()
        assert c2.option('b').owner.isdefault()
        c.option('b').value.set(False)
        assert c.option('b').owner.get() == 'user'
        assert c2.option('b').owner.get() == 'user'
        c.option('b').owner.set('persistent')
        assert c.option('b').owner.get() == 'persistent'
        assert c2.option('b').owner.get() == 'persistent'
        delete_session('test_persistent')


def test_create_persistent_retrieve_information():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.information.set('info', 'string')
        assert c.information.get('info') == 'string'
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.information.get('info') == 'string'
        delete_session(c.config.name())
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.information.get('info', None) is None
        delete_session(c.config.name())
        del c


def test_two_persistent_information():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.property.pop('cache')
        c.information.set('info', 'string')
        assert c.information.get('info') == 'string'
        c2 = Config(o, session_id='test_persistent', persistent=True)
        c2.property.pop('cache')
        assert c2.information.get('info') == 'string'
        delete_session('test_persistent')


def test_two_different_persistents():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.property.pop('cache')
        d = Config(o, session_id='test_persistent2', persistent=True)
        d.property.pop('cache')
        c.option('b').property.add('test')
        assert c.option('b').property.get() == {'test'}
        assert d.option('b').property.get() == set()
        assert c.option('b').value.get() is None
        assert d.option('b').value.get() is None
        c.option('b').value.set(True)
        assert c.option('b').value.get() == True
        assert d.option('b').value.get() is None

        delete_session('test_persistent')
        delete_session('test_persistent2')


def test_two_different_information():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.information.set('a', 'a')
        d = Config(o, session_id='test_persistent2', persistent=True)
        d.information.set('a', 'b')
        assert c.information.get('a') == 'a'
        assert d.information.get('a') == 'b'

        delete_session('test_persistent')
        delete_session('test_persistent2')


def test_exportation_importation():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        d = Config(o, session_id='test_persistent2', persistent=True)
        e = Config(o, session_id='test_persistent3', persistent=True)
        c.owner.set('export')
        assert c.option('b').value.get() is None
        c.option('b').value.set(True)
        assert c.option('b').value.get() is True
        assert c.owner.get() == 'export'
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert c.owner.get() == 'export'
        assert c.value.exportation() == [['b'], [None], [True], ['export']]
        d.value.importation(c.value.exportation())
        assert c.value.exportation() == [['b'], [None], [True], ['export']]
        assert c.owner.get() == 'export'
        assert d.value.exportation() == [['b'], [None], [True], ['export']]
        assert d.owner.get() == 'user'
        del d
        #
        d = Config(o, session_id='test_persistent2', persistent=True)
        assert d.value.exportation() == [['b'], [None], [True], ['export']]
        assert d.owner.get() == 'user'
        #
        e.value.importation(c.value.exportation(with_default_owner=True))
        assert e.value.exportation() == [['b'], [None], [True], ['export']]
        assert e.owner.get() == 'export'
        del e
        #
        e = Config(o, session_id='test_persistent3', persistent=True)
        assert e.value.exportation() == [['b'], [None], [True], ['export']]
        assert e.owner.get() == 'export'
        #
        delete_session('test_persistent')
        delete_session('test_persistent2')
        delete_session('test_persistent3')


def test_create_persistent_context_property():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.property.add('persistent')
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert 'persistent' in c.property.get()
        del c
        delete_session('test_persistent')


def test_create_persistent_context_property_metaconfig():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.property.add('persistent')
        del c
        #
        m = MetaConfig([], optiondescription=o)
        c = m.config.new(session_id='test_persistent', persistent=True)
        assert 'persistent' in c.property.get()
        del c
        delete_session('test_persistent')


def test_create_persistent_property():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    if default_storage.is_persistent():
        c = Config(o, session_id='test_persistent', persistent=True)
        c.option('b').property.add('persistent')
        del c
        #
        c = Config(o, session_id='test_persistent', persistent=True)
        assert 'persistent' in c.option('b').property.get()
        del c
        delete_session('test_persistent')