import os
import time
import random
from threading import Thread
from atom.api import (Atom, Str, Range, ContainerList, Bool)

from enamlx.widgets.table_view import (
    TableView, TableViewRow, TableViewItem
)

from enaml.widgets.api import (
    Window, Container, PushButton, CheckBox, RadioButton
)
from enaml.core.looper import Looper
from enaml.widgets.spin_box import SpinBox
from enaml.image import Image
from enaml.icon import Icon,IconImage
from enaml.application import deferred_call
from enaml.widgets.menu import Menu
from enaml.widgets.action import Action
from enamlx.core.looper import ListLooper

def icon_path(name):
    path = os.getcwd()
    return os.path.join(path,'../','images','icons','%s.png'%name)

def load_image(name):
    with open(icon_path(name),'rb') as f:
        data = f.read()
    return Image(data=data)

def load_icon(name):
    img = load_image(name)
    icg = IconImage(image=img) 
    return Icon(images=[icg])

class Person(Atom):
    """ A simple class representing a person object.

    """
    last_name = Str()

    first_name = Str()

    age = Range(low=0)

    debug = Bool(False)
    
    def __repr__(self, *args, **kwargs):
        return "Person(first_name={p.first_name},last_name={p.last_name})".format(p=self)

class TableModel(Atom):
    people = ContainerList(Person)
    
    def add_person(self):
        #people = self.people[:]
        for i in range(100):
            age = len(self.people)
            person = Person(last_name='Doe-{}'.format(age),first_name='John-{}'.format(age),age=age)
            #people.append(person)
            self.people.insert(0,person)
    
    def remove_person(self):
        #people = self.people[:]
        #people.pop()
        self.people.pop()
        

data_model = TableModel(people=[
    Person(last_name='Barker-%i'%i,
           first_name='Bob%i'%i,
           age=i,
           debug=bool(i&1))
    for i in range(1000000) # 10000
])

def update_data():
    """ Test what happens when we update text!"""
    while True:
        time.sleep(1)
        
        def update():
            person = data_model.people[random.randint(0,10)]
            print("Updating %s"%person)
            # Always update in the ui thread!
            person.debug = not person.debug
        deferred_call(update)
        # It flipping works!

t = Thread(target=update_data)
t.daemon=True
t.start()

enamldef Main(Window):
    attr model = data_model
    Container:
        PushButton:
            text = 'Add person'
            clicked :: model.add_person()
        PushButton:
            text = 'Remove person'
            clicked :: model.remove_person()
            
        TableView: table:
            minimum_size = (640,360)
            horizontal_headers << ['#','First','Last','Age','Color']#,str(table.visible_rows)]
            horizontal_stretch = True
            horizontal_sizes = [10, 100, 100, 20, 30]
            items << model.people
            
            Looper:
                #: Max number of visible rows
                #: If this number is too small, stuff will get jacked
                iterable << range(table.visible_rows)
                TableViewRow:
                    row << table.visible_row+loop_index
                    attr person << table.items[self.row]
                    clicked :: print("Row %s clicked!"%self.row)
                    
                    Menu:
                        Action:
                            text << 'Row {} menu'.format(table.visible_row+loop_index)
                            triggered :: 'Clicked row'
                    
                    TableViewItem:
                        checkable = True
                        checked := person.debug
                        toggled :: print("toggled %s"%self.row)
                        icon << person.debug and load_icon('bug') or None
                    TableViewItem:
                        text := person.first_name
                        clicked :: print("Clicked %s"%person.first_name)
                        Menu:
                            Action:
                                text << 'Edit {} menu'.format(person.first_name)
                                triggered :: 'Clicked edit'
                    TableViewItem:
                        text << person.last_name
                        double_clicked :: print("Double clicked %s"%person.last_name)
                        selected :: print("Selection %s is now %s"%(person.last_name,change['value']))
                    TableViewItem:
                        text = 'Loading...'
                        editable = True
                        # TODO: Delegate widgets Not yet implemented
                        SpinBox:
                            value := person.age
                    TableViewItem:
                        text << str(parent.row)
                        foreground << parent.row&1 and 'red' or 'blue'
                        background = 'green'
                        text_alignment = ('center','top')
            
