import wx
import wx.grid as gridlib


class HugeTable(gridlib.GridTableBase):
    def __init__(self, log, parent):
        gridlib.GridTableBase.__init__(self)
        self.parent = parent
        self.log = log
        self.show_default_values = True
        self.odd=gridlib.GridCellAttr()
        self.odd.SetBackgroundColour("sky blue")
        self.even=gridlib.GridCellAttr()
        self.even.SetBackgroundColour("sea green")
        self.filter_editors = []
        self.filter_attrs = []
        for i in range(self.GetNumberCols()):
            fa = gridlib.GridCellAttr()
            fa.SetBackgroundColour("sea green")
            self.filter_attrs.append(fa)
            fe = gridlib.GridCellChoiceEditor(['FILTER data', 'WHERE=', 'CONTAINS', '???'], True)
            self.filter_editors.append(fe)
            fa.SetEditor(fe)

    def GetAttr(self, row, col, kind):
        if row == 0:
            print(f'GetAttr row 0 col {col} fe created {self.filter_editors[col].IsCreated()}')
            attr = self.filter_attrs[col] #self.filter_editors[col][0]
            if self.filter_editors[col].IsCreated():
                self.filter_editors[col].IncRef()
        else:
            attr = [self.even, self.odd][row % 2]
        attr.IncRef()
        return attr

    # This is all it takes to make a custom data table to plug into a
    # wxGrid.  There are many more methods that can be overridden, but
    # the ones shown below are the required ones.  This table simply
    # provides strings containing the row and column values.

    def GetNumberRows(self):
        return 10000

    def GetNumberCols(self):
        return 5

    def IsEmptyCell(self, row, col):
        return False

    def GetValue(self, row, col):
        if row == 0:
            print(f'GetValue row {row} col {col}')
            if self.filter_editors[col].IsCreated():
                print(f'GetValue filter_editor IsCreated r {row} c {col}')
                val = self.filter_editors[col].GetValue()
            else:
                val = 'FILTER data'
            return val
        if self.show_default_values:
            return str((row, col))
        return "Off"

    def SetValue(self, row, col, value):
        print('SetValue(%d, %d, "%s") ignored.\n' % (row, col, value))

        if row==0 and self.filter_editors[col].IsCreated():
            self.show_default_values = not self.show_default_values
            self.parent.Refresh()


#---------------------------------------------------------------------------

class HugeTableGrid(gridlib.Grid):
    def __init__(self, parent, log):
        gridlib.Grid.__init__(self, parent, -1)

        table = HugeTable(log, parent)
        self.table = table
        self.parent = parent

        # The second parameter means that the grid is to take
        # ownership of the table and will destroy it when done.
        # Otherwise you would need to keep a reference to it, but that
        # would allow other grids to use the same table.
        self.SetTable(table, True)

        self.Bind(gridlib.EVT_GRID_CELL_RIGHT_CLICK, self.OnRightDown)
        self.Bind(gridlib.EVT_GRID_EDITOR_SHOWN, self.OnEditorShown)
        self.Bind(gridlib.EVT_GRID_EDITOR_HIDDEN, self.OnEditorHidden)
        self.Bind(gridlib.EVT_GRID_EDITOR_CREATED, self.OnEditorCreated)

    def OnEditorShown(self, evt):
        # if evt.GetRow() == 0 and evt.GetCol() == 0 and \
        #         wx.MessageBox("Are you sure you wish to edit this cell?",
        #                       "Checking", wx.YES_NO) == wx.NO:
        #     evt.Veto()
        #     return
        print("OnEditorShown: (%d,%d) %s\n" % (evt.GetRow(), evt.GetCol(),
                                         evt.GetPosition()))
        evt.Skip()

    def OnEditorHidden(self, evt):
        # if evt.GetRow() == 0 and evt.GetCol() == 0 and \
        #         wx.MessageBox("Are you sure you wish to  finish editing this cell?",
        #                       "Checking", wx.YES_NO) == wx.NO:
        #     evt.Veto()
        #     return
        print("OnEditorHidden: (%d,%d) %s\n" % (evt.GetRow(),
                                                evt.GetCol(),
                                                evt.GetPosition()))
        evt.Skip()

    def OnEditorCreated(self, evt):
        print("OnEditorCreated: (%d, %d) %s\n" % (evt.GetRow(),
                                                  evt.GetCol(),
                                                  evt.GetControl()))

    def OnRightDown(self, event):
        print("OnRightDown")
        print(self.GetSelectedRows())

    def OnClose(self, event):
        print('OnClose')
        self.Hide()
        for i, fa in enumerate(self.table.filter_attrs):
            fe = self.table.filter_editors[i]
            if fe.IsCreated():
                if fe.Control:
                    print('hiding filter_editor control')
                    fe.Control.Hide()
            print(f'OnClose FilterAttr   refcount    {fa.RefCount}  col {i}')
            print(f'OnClose FilterEditor refcount    {fe.RefCount}  col {i}')
            while fa.RefCount > 1:
                fa.DecRef()
                print(f'OnClose DecRef FilterAttr   col {i}')
            while fe.RefCount > 1:
                fe.DecRef()
                print(f'OnClose DecRef FilterEditor col {i}')
        while self.table.odd.RefCount>1:
            self.table.odd.DecRef()
            print('DecRef odd')

        while self.table.even.RefCount>1:
            self.table.even.DecRef()
            print('DecRef even')
        print('OnClose END')
        #event.Skip()
        self.parent.Destroy()


#---------------------------------------------------------------------------

class TestFrame(wx.Frame):
    def __init__(self, parent, log):
        wx.Frame.__init__(self, parent, -1, "Huge (virtual) Table Demo", size=(640,480))
        grid = HugeTableGrid(self, log)

        grid.SetReadOnly(5,5, True)
        self.Bind(wx.EVT_CLOSE, grid.OnClose)


#---------------------------------------------------------------------------

if __name__ == '__main__':
    import sys
    app = wx.App()
    frame = TestFrame(None, sys.stdout)
    frame.Show(True)
    app.MainLoop()
