# -*- coding: utf-8 -*-
# Editobj3
# Copyright (C) 2007-2014 Jean-Baptiste LAMY

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


import unittest

import editobj3
import editobj3.introsp as introsp
import editobj3.observe as observe
import editobj3.field   as field


class IntrospTest(object):
  def __init__(self):
    self.a = 0
    self.x = 0
    self.y = 0
    self.z = 0

  def get_x(self): return self.x
  def set_x(self, x): self.x = x

  def getY(self): return self.y
  def setY(self, y): self.y = y

  def set_z(self, z): self.z = z

  def set_b(self, b): pass
  b = property(None, set_b)
  
  def get_c(self): return 1

class TestIntrosp(unittest.TestCase):
  def setUp(self):
    pass
    
  def test_1(self):
    d = introsp.description(IntrospTest)
    assert set(d.attributes.keys()) == set(["b", "c", "x", "y", "z"])
    assert d.attributes["b"].get_method is None
    assert d.attributes["b"].set_method is not None
    assert d.attributes["c"].get_method == "get_c"
    assert d.attributes["c"].set_method is not None
    assert d.attributes["x"].get_method == "get_x"
    assert d.attributes["x"].set_method == "set_x"
    assert d.attributes["y"].get_method == "getY"
    assert d.attributes["y"].set_method == "setY"
    assert d.attributes["z"].get_method is not None
    assert d.attributes["z"].set_method == "set_z"
    
    d.def_attr("a", field.HiddenField)
    i = IntrospTest()
    attributes = d.attributes_of(i)
    attributes = { attribute.name : attribute for attribute in attributes }
    print(attributes)
    assert attributes["a"].field_class_for(i) is field.HiddenField
    
  def test_getset_2(self):
    d = introsp.description(IntrospTest)
    i = IntrospTest()
    attributes = d.attributes_of(i)
    assert set(attribute.name for attribute in attributes) == set(['a', 'c', 'b', 'y', 'x', 'z'])
    
    

class C(object):
  pass

class TestObserve(unittest.TestCase):
  def setUp(self):
    self.listened = None
    
  def listener(self, *args): self.listened = args
  
  def test_object_1(self):
    c = C()
    observe.observe(c, self.listener)
    observe.scan()
    assert not self.listened
    c.x = 1
    observe.scan()
    assert self.listened == (c, object, {"x" : 1}, {})
  
  def test_object_2(self):
    c = C()
    observe.observe(c, self.listener)
    observe.scan()
    assert not self.listened
    c.x = 1
    c.y = "e"
    observe.scan()
    assert self.listened == (c, object, {"x" : 1, "y" : "e"}, {})
    
    
  def test_list_1(self):
    c = [0]
    observe.observe(c, self.listener)
    observe.scan()
    assert not self.listened
    c.append(1)
    observe.scan()
    assert self.listened == (c, list, [0, 1], [0])
    c.remove(0)
    observe.scan()
    assert self.listened == (c, list, [1], [0, 1])
    
    
  def test_set_1(self):
    c = set([0])
    observe.observe(c, self.listener)
    observe.scan()
    assert not self.listened
    c.add(1)
    observe.scan()
    assert self.listened == (c, set, set([0, 1]), set([0]))
    c.remove(0)
    observe.scan()
    assert self.listened == (c, set, set([1]), set([0, 1]))
    
   
  def test_tree_1(self):
    c  = C()
    c2 = C()
    c.l = [c2]
    observe.observe_tree(c, self.listener)
    assert observe.isobserved(c)
    assert observe.isobserved(c2)
    observe.unobserve_tree(c, self.listener)
    assert not observe.isobserved(c)
    assert not observe.isobserved(c2)
    
  def test_tree_2(self):
    c  = C()
    c2 = C()
    c.l = (1, 2, c2)
    observe.observe_tree(c, self.listener)
    assert observe.isobserved(c)
    assert observe.isobserved(c2)
    c.l = 1
    observe.scan()
    assert observe.isobserved(c)
    assert not observe.isobserved(c2)
    
    observe.unobserve_tree(c, self.listener)
    assert not observe.isobserved(c)
    assert not observe.isobserved(c2)
    
  def test_tree_3(self):
    c  = C()
    c2 = C()
    c.l = set([1, 2, c2])
    observe.observe_tree(c, self.listener)
    assert observe.isobserved(c)
    assert observe.isobserved(c2)
    
    observe.unobserve_tree(c, self.listener)
    assert not observe.isobserved(c)
    assert not observe.isobserved(c2)
    
  def test_tree_4(self):
    c  = C()
    c2 = C()
    c.l = []
    observe.observe_tree(c, self.listener)
    c.l.append(c2)
    observe.scan()
    assert observe.isobserved(c)
    assert observe.isobserved(c2)
    c.l.remove(c2)
    observe.scan()
    assert observe.isobserved(c)
    assert not observe.isobserved(c2)
    
    observe.unobserve_tree(c, self.listener)
    assert not observe.isobserved(c)
    assert not observe.isobserved(c2)
    
  def test_tree_5(self):
    c  = C()
    c2 = C()
    c .c = c2
    c2.c = c
    observe.observe_tree(c, self.listener)
    assert observe.isobserved(c)
    assert observe.isobserved(c2)
    
    observe.unobserve_tree(c, self.listener)
    assert not observe.isobserved(c)
    assert not observe.isobserved(c2)


if __name__ == '__main__':
  unittest.main()
  
