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

from tiramisu.config import Config, GroupConfig, MetaConfig
from tiramisu.option import BoolOption, IntOption, StrOption, OptionDescription, submulti
import weakref


IS_DEREFABLE = True


def test_deref_storage():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(c.cfgimpl_get_values()._p_)
    del(c)
    assert w() is None


def test_deref_value():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(c.cfgimpl_get_values())
    del(c)
    assert w() is None


def test_deref_setting():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(c.cfgimpl_get_settings())
    del(c)
    assert w() is None


def test_deref_config():
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(c)
    del(c)
    assert w() is None


def test_deref_option():
    global IS_DEREFABLE
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    w = weakref.ref(b)
    del(b)
    try:
        assert w() is not None
    except AssertionError:
        IS_DEREFABLE = False
        return
    del(o)
    assert w() is None


def test_deref_optiondescription():
    if not IS_DEREFABLE:
        return
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    w = weakref.ref(o)
    del(b)
    assert w() is not None
    del(o)
    assert w() is None


def test_deref_option_cache():
    if not IS_DEREFABLE:
        return
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    o.impl_build_cache_option()
    w = weakref.ref(b)
    del(b)
    assert w() is not None
    del(o)
    assert w() is None


def test_deref_optiondescription_cache():
    if not IS_DEREFABLE:
        return
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    o.impl_build_cache_option()
    w = weakref.ref(o)
    del(b)
    assert w() is not None
    del(o)
    assert w() is None


def test_deref_option_config():
    if not IS_DEREFABLE:
        return
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(b)
    del(b)
    assert w() is not None
    del(o)
    assert w() is not None
    del(c)
    assert w() is None


def test_deref_optiondescription_config():
    if not IS_DEREFABLE:
        return
    b = BoolOption('b', '')
    o = OptionDescription('od', '', [b])
    c = Config(o)
    w = weakref.ref(o)
    del(b)
    assert w() is not None
    del(o)
    assert w() is not None
    del(c)
    assert w() is None


def test_deref_groupconfig():
    if not IS_DEREFABLE:
        return
    i1 = IntOption('i1', '')
    od1 = OptionDescription('od1', '', [i1])
    od2 = OptionDescription('od2', '', [od1])
    conf1 = Config(od2, 'conf1')
    conf2 = Config(od2, 'conf2')
    meta = GroupConfig([conf1, conf2])
    w = weakref.ref(conf1)
    del(conf1)
    assert w() is not None
    del(meta)
    assert w() is None


def test_deref_metaconfig():
    if not IS_DEREFABLE:
        return
    i1 = IntOption('i1', '')
    od1 = OptionDescription('od1', '', [i1])
    od2 = OptionDescription('od2', '', [od1])
    conf1 = Config(od2, 'conf1')
    conf2 = Config(od2, 'conf2')
    meta = MetaConfig([conf1, conf2])
    w = weakref.ref(conf1)
    del(conf1)
    assert w() is not None
    del(meta)
    assert w() is None


def test_deref_submulti():
    if not IS_DEREFABLE:
        return
    multi = StrOption('multi', '', multi=submulti)
    od = OptionDescription('od', '', [multi])
    cfg = Config(od)
    cfg.cfgimpl_get_settings().remove('cache')
    w = weakref.ref(cfg.multi)
    assert w() is None
    cfg.multi.append([])
    w = weakref.ref(cfg.multi)
    assert w() is None
    m = cfg.multi
    w = weakref.ref(m)
    z = weakref.ref(w()[0])
    del(m)
    assert w() is None
    assert z() is None