# AUTOGENERATED! DO NOT EDIT! File to edit: nbs/views.ratio.ipynb (unless otherwise specified).

__all__ = ['RatioLandingView', 'RatioLanding', 'ColorInt', 'RatioEstimatesView', 'RatioEstimates']

# Cell
from ..items import ItemList, ItemArray
from ..widget_containers import VBox, HBox
from ..widgets import Text, Dropdown, Button, Grid, FloatText, AlignedLabel, IntLabel, IntText
from ..rpy import DTYPES
from ..models.ratio import RatioEstimatesModel, Ratios
from ..mvc import Controller

# Cell
import traitlets
from traitlets import Unicode, observe, validate, Int
import ipywidgets as ipyw
import numpy as np

# Cell
class RatioLandingView(VBox):

    def __init__(self, rowMax=6, colMax=6, **kwargs):
        super().__init__(**kwargs)

        ''' rowBox widgets'''
        self.rowName = Text(description='Factor:', layout=ipyw.Layout( max_width = '160px'))
        options=[i for i in range(2, rowMax + 1)]
        self.n_row = Dropdown(description='Levels:', layout=ipyw.Layout(width='135px'), options=options)

        rowLevels = [Text(layout=ipyw.Layout(max_width = '62px')) for i in range(rowMax)]
        rowLevels[0].description = 'Names:'
        rowLevels[0].layout.max_width = '150px'
        self.rowLevels = ItemList(rowLevels)

        ''' columnBox widgets '''
        self.colName = Text(description='Factor:', layout=ipyw.Layout( max_width = '160px'))
        options = [i for i in range(2, colMax + 1)]
        self.n_col  = Dropdown(description='Levels:', layout=ipyw.Layout(width='135px'), options=options)

        colLevels = [Text(layout=ipyw.Layout(max_width = '62px')) for i in range(colMax)]
        colLevels[0].description = 'Names:'
        colLevels[0].layout.max_width = '150px'
        self.colLevels = ItemList(colLevels)

        ''' add children '''
        self.rowBox = HBox()
        self.rowBox.children += (self.rowName, self.n_row) + self.rowLevels.children
        self.colBox = HBox()
        self.colBox.children += (self.colName, self.n_col) + self.colLevels.children
        self.children = (self.rowBox, self.colBox)

# Cell
class RatioLanding( Controller, RatioLandingView):

    def __init__(self, model, **kwargs):
        super().__init__(model.rowMax, model.colMax,**kwargs)

        self.model = model
        self.initialize()

        ''' link widgets traits to model '''
        traitlets.link((self.model, 'rowName'), (self.rowName, 'value'))
        traitlets.link((self.model, 'colName'), (self.colName, 'value'))
        traitlets.link((self.model, 'n_row'), (self.n_row, 'value'))
        traitlets.link((self.model, 'n_col'), (self.n_col, 'value'))

        ''' observe'''
        self.n_row.observe(self.observe_n_row, names='value')
        self.n_col.observe(self.observe_n_col, names='value')
        self.rowLevels.observe(self.changeRowLevels, 'value', type='child_change')


    def initialize(self):
        self.rowName.value = self.model.rowName
        self.colName.value = self.model.colName
        self.n_row.value = self.model.n_row
        self.n_col.value = self.model.n_col
        self.rowLevels.set_list(self.model.rowLevels)
        self.colLevels.set_list(self.model.colLevels)

    def observe_n_row(self, change):
        for i in range(2, change['new']):
            self.rowLevels[i].visible()
        for i in range(change['new'], 6):
            self.rowLevels[i].invisible()
        return change

    def observe_n_col(self, change):
        for i in range(2, change['new']):
            self.colLevels[i].visible()
        for i in range(change['new'], 6):
            self.colLevels[i].invisible()
        return change

    def changeRowLevels(self, change):
        i = change['index']
        value = change['new']
        self.model.rowLevels[i] = value
        self.rowLevels[i].value = value

# Cell
class ColorInt(Button):

    value = Int(0)
    color = Unicode('none')

    def __init__(self, width='auto', height='auto', **kwargs):
        super().__init__(**kwargs)
        self.description = str(self.value)
        self.on_click(self._on_click)

    @observe('value')
    def _on_value_change(self, proposal):
        self.description = str(self.value)

    @validate('color')
    def _valid_value(self, proposal):
        if proposal['value'] not in ('red', 'green', 'none'):
            raise TraitError('Invalid color: Valid colors are red, green, and none')
        return proposal['value']

    @observe('color')
    def _observe_color(self, b):
        if self.color == 'red':
            self.layout.border='3px solid red'
        elif self.color == 'green':
            self.layout.border='3px solid green'
        elif self.color == 'none':
            self.layout.border='none'

    def _on_click(self, button):
        if button.color == 'red':
            button.color = 'green'
        elif button.color == 'green':
            button.color = 'none'
        elif button.color == 'none':
            button.color = 'red'

# Cell
class RatioEstimatesView(Grid):

    def __init__(self, n_row=6, n_col=6, decimals=3, **kwargs):
        grid_rows = int(n_row+3)
        grid_cols = int(n_col+3)
        super().__init__(grid_rows, grid_cols, width='100%', **kwargs)


        '''layouts'''
        # note: min_width prevents overflow
        # https://css-tricks.com/equal-width-columns-in-css-grid-are-kinda-weird/
        layout = {'min_width':'60px', 'width':'auto', 'height':'auto'}

        rowRatios = [FloatText(#step=1/10**self.model.rowRatios.decimals, value=self.model.rowRatios[i],
                               layout=ipyw.Layout(**layout)) for i in range(n_row)]
        self.rowRatios = ItemList(rowRatios)
        self.add_widget_list(self.rowRatios, 2, 0, direction='col')

        colRatios = [FloatText(#step=1/10**self.model.colRatios.decimals, value=self.model.colRatios[i],
                               layout=ipyw.Layout(**layout)) for i in range(n_col)]
        self.colRatios = ItemList(colRatios)
        self.add_widget_list(self.colRatios, 0, 2, direction='row')


        colorIntArray = [ColorInt(layout=ipyw.Layout(**layout)) for j in range(n_col) for i in range(n_row)]
        self.colorIntArray = ItemArray(n_row, n_col, colorIntArray, traits=('value', 'color'))
        self.add_widget_array(self.colorIntArray, 2, 2)

        widget_list = [AlignedLabel(layout=ipyw.Layout(**layout)) for i in range(n_row)]
        self.rowLevelNames = ItemList(widget_list)
        self.add_widget_list(self.rowLevelNames, 2, 1, direction='col')

        widget_list = [AlignedLabel(layout=ipyw.Layout(**layout)) for i in range(n_col)]
        self.colLevelNames = ItemList(widget_list)
        self.add_widget_list(self.colLevelNames, 1, 2, direction='row')

        widget_list = [IntLabel(layout=ipyw.Layout(**layout)) for i in range(n_row)]
        self.rowTotals = ItemList(widget_list)
        self.add_widget_list(self.rowTotals, 2, n_col + 2, direction='col')


        widget_list = [IntLabel(layout=ipyw.Layout(**layout)) for i in range(n_col)]
        self.colTotals = ItemList(widget_list)
        self.add_widget_list(self.colTotals, n_row + 2, 2, direction='row')

        self.total = IntText(layout=ipyw.Layout(**layout))
        self.add_widget_list([self.total], n_row + 2, n_col+2)

# Cell
class RatioEstimates(RatioEstimatesView, Controller):

    def __init__(self, model, **kwargs):
        super().__init__(model.n_row, model.n_col, **kwargs)

        self.model = model
        self.initialize()

        ''' link '''
        traitlets.link((self.model, 'total'), (self.total, 'value'))

        ''' observe '''
        self.total.observe(self.observeTotal)
        self.rowRatios.observe(self.observeRowRatios, type='child_change')
        self.colRatios.observe(self.observeColRatios, type='child_change')

    def initialize(self):
        for ratio in self.rowRatios:
            ratio.step = self.model.rowRatios.step
        for ratio in self.colRatios:
            ratio.step = self.model.colRatios.step
        self.rowRatios.unobserve(self.observeRowRatios, type='child_change')
        self.rowRatios.set_list(self.model.rowRatios)
        self.rowRatios.observe(self.observeRowRatios, type='child_change')
        self.colRatios.unobserve(self.observeColRatios, type='child_change')
        self.colRatios.set_list(self.model.colRatios)
        self.colRatios.observe(self.observeColRatios, type='child_change')
        self.colorIntArray.set_array(self.model.ns_cells, 'value')
        self.colorIntArray.set_array(self.model.colors, 'color')
        self.rowLevelNames.set_list(self.model.rowLevelNames)
        self.colLevelNames.set_list(self.model.colLevelNames)
        self.rowTotals.set_list(self.model.rowTotals)
        self.colTotals.set_list(self.model.colTotals)

    def onAnyChange(self):
        self.colorIntArray.set_array(self.model.ns_cells)
        self.rowTotals.set_list(self.model.rowTotals)
        self.colTotals.set_list(self.model.colTotals)

    def observeTotal(self, change):
        self.onAnyChange()

    def observeRowRatios(self, change):
        self.model.incRowRatio(change['index'], change['new'] - change['old'])
        self.rowRatios.unobserve_children('value')
        self.rowRatios.set_list(self.model.rowRatios)
        self.rowRatios.observe_children('value')
        self.onAnyChange()

    def observeColRatios(self, change):
        self.model.incColRatio(change['index'], change['new'] - change['old'])
        self.colRatios.unobserve_children('value')
        self.colRatios.set_list(self.model.colRatios)
        self.colRatios.observe_children('value')
        self.onAnyChange()