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

from tiramisu.setting import owners
from tiramisu.option import ChoiceOption, StrOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError

from py.test import raises


def return_val(val):
    return val


def return_list():
    return ['val1', 'val2']


def return_calc_list(val):
    return [val]


def return_error():
    raise Exception('test')


def test_choiceoption():
    ch = ChoiceOption('ch', '', values=('val1', 'val2'))
    od = OptionDescription('od', '', [ch])
    cfg = Config(od)
    cfg.read_write()
    owner = cfg.cfgimpl_get_settings().getowner()
    assert cfg.getowner(ch) == owners.default
    cfg.ch = 'val1'
    assert cfg.getowner(ch) == owner
    del(cfg.ch)
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch='no'")
    assert cfg.getowner(ch) == owners.default
    assert ch.impl_get_values(cfg) == ('val1', 'val2')


def test_choiceoption_function():
    ch = ChoiceOption('ch', '', values=return_list)
    od = OptionDescription('od', '', [ch])
    cfg = Config(od)
    cfg.read_write()
    owner = cfg.cfgimpl_get_settings().getowner()
    assert cfg.getowner(ch) == owners.default
    cfg.ch = 'val1'
    assert cfg.getowner(ch) == owner
    del(cfg.ch)
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch='no'")
    assert cfg.getowner(ch) == owners.default
    assert ch.impl_get_values(None) == []
    assert ch.impl_get_values(cfg) == ['val1', 'val2']


def test_choiceoption_function_error():
    ch = ChoiceOption('ch', '', values=return_error)
    od = OptionDescription('od', '', [ch])
    cfg = Config(od)
    cfg.read_write()
    raises(Exception, "cfg.ch = 'no'")


def test_choiceoption_calc_function():
    ch = ChoiceOption('ch', "", values=return_calc_list, values_params={'': ('val1',)})
    od = OptionDescription('od', '', [ch])
    cfg = Config(od)
    cfg.read_write()
    owner = cfg.cfgimpl_get_settings().getowner()
    assert cfg.getowner(ch) == owners.default
    cfg.ch = 'val1'
    assert cfg.getowner(ch) == owner
    del(cfg.ch)
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch='no'")
    assert cfg.getowner(ch) == owners.default


def test_choiceoption_calc_opt_function():
    st = StrOption('st', '', 'val1')
    ch = ChoiceOption('ch', "", values=return_calc_list, values_params={'': ((st, False),)})
    od = OptionDescription('od', '', [st, ch])
    cfg = Config(od)
    cfg.read_write()
    owner = cfg.cfgimpl_get_settings().getowner()
    assert cfg.getowner(ch) == owners.default
    cfg.ch = 'val1'
    assert cfg.getowner(ch) == owner
    del(cfg.ch)
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch='no'")
    assert cfg.getowner(ch) == owners.default


def test_choiceoption_calc_opt_function_propertyerror():
    st = StrOption('st', '', 'val1', properties=('disabled',))
    ch = ChoiceOption('ch', "", values=return_calc_list, values_params={'': ((st, False),)})
    od = OptionDescription('od', '', [st, ch])
    cfg = Config(od)
    cfg.read_write()
    raises(ValueError, "cfg.ch='no'")


def test_choiceoption_calc_opt_multi_function():
    st = StrOption('st', '', ['val1'], multi=True)
    ch = ChoiceOption('ch', "", default_multi='val2', values=return_val, values_params={'': ((st, False),)}, multi=True)
    ch2 = ChoiceOption('ch2', "", default=['val2'], values=return_val, values_params={'': ((st, False),)}, multi=True)
    od = OptionDescription('od', '', [st, ch, ch2])
    cfg = Config(od)
    cfg.read_write()
    assert cfg.ch == []
    owner = cfg.cfgimpl_get_settings().getowner()
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch.append()")
    cfg.ch = ['val1']
    assert cfg.getowner(ch) == owner
    del(cfg.ch)
    assert cfg.getowner(ch) == owners.default
    raises(ValueError, "cfg.ch='no'")
    assert cfg.getowner(ch) == owners.default
    #
    raises(ValueError, "cfg.ch2")


def test_choiceoption_calc_invalid():
    st = StrOption('st', '', ['val1'], multi=True)
    st
    raises(ValueError, "ch = ChoiceOption('ch', '', default_multi='val2', values=[1, 2, 3], values_params={'': ((st, False),)}, multi=True)")


def test_choiceoption_calc_not_list():
    st = StrOption('st', '', 'val1')
    ch = ChoiceOption('ch', "", default_multi='val2', values=return_val, values_params={'': ((st, False),)}, multi=True)
    od = OptionDescription('od', '', [st, ch])
    cfg = Config(od)
    cfg.read_write()
    raises(ConfigError, "cfg.ch = ['val1']")