#
#   Imandra Inc.
#
#   sketches.py
#

from textual import on
from textual.app import App, ComposeResult
from textual.containers import Horizontal, Vertical
from textual.reactive import reactive
from textual.screen import Screen
from textual.widgets import (
    Button,
    Footer,
    Input,
    Label,
    ListItem,
    ListView,
    Rule,
    Select,
    Static,
    TabbedContent,
    TabPane,
    TextArea,
)

from codelogician.sketch.container import SketchContainer
from codelogician.sketch.sketch import (
    Sketch,
    SketchState,
)
from codelogician.ui.common import MyHeader, bind
from codelogician.util import maybe


class SketchScreen(Screen):
    """
    SketchScreen
    """

    #    mmodel = reactive("", recompose=True)
    sketch_container: reactive[None | SketchContainer] = reactive(None, recompose=True)
    selected_sketch: reactive[None | Sketch] = reactive(None)
    selected_sketch_state: reactive[None | SketchState] = reactive(None)

    def __init__(self):
        """ """
        Screen.__init__(self)

        self.title = 'Sketches'
        bind(self, 'sketch_container')

    def upd_static(self, selector, text):
        self.query_one(selector, Static).update(text)

    def watch_selected_sketch(self):
        """
        Updated state of the selected sketch
        """

        sk: None | Sketch = self.selected_sketch

        if not sk:
            return
        # fmt: off
        self.upd_static('#sk_sketch_id', f'ID : {sk.sketch_id}')
        self.upd_static('#sk_anchor_model_path', f'Anchor model: {sk.anchor_model_path}')
        self.upd_static('#sk_processing', f'Is processing: {sk.processing}')
        # fmt: on

        state_list: ListView = self.query_one('#sketch_state_list_view', ListView)
        state_list.clear()
        state_list.extend([ListItem(Static(str(idx))) for idx in sk.state_ids()])
        state_list.index = 0  # let's select the first one

        # Let's also make sure that the next tab has 'Existing sketch' selected
        self.query_one('#tabbed_content', TabbedContent).active = 'tab_existing'

    def watch_selected_sketch_state(self):
        """
        Update the specific sketch state
        """

        state: None | SketchState = self.selected_sketch_state

        if not state:
            return

        # fmt: off
        self.upd_static('#sketch_state_id', f'State id: {state.state_id}')
        self.upd_static('#sketch_state_change', f'State change: {str(state.change)}')
        self.upd_static('#sketch_state_frm_status', f'Formalization status: {str(state.status)}')
        self.upd_static('#sketch_state_error', f'Error: {state.error if state.error else "N/A"}')
        # fmt: on
        self.query_one('#sketch_state_iml', TextArea).text = state.iml_code

    def compose(self) -> ComposeResult:
        """ """
        yield MyHeader()

        with Horizontal() as h:
            h.styles.layout = 'grid'
            h.styles.grid_size_columns = 2
            h.styles.grid_columns = '1fr 3fr'

            with Vertical():
                yield Static('Existing sketches:')
                if self.sketch_container:
                    if self.sketch_container.ids():
                        items = []
                        for sketch_id in self.sketch_container.ids():
                            items.append(ListItem(Label(sketch_id)))
                        yield (ListView(*items, id='sketch_list_view'))
                    else:
                        yield Static('N/A')
                else:
                    yield Static('N/A')

            with TabbedContent(id='tabbed_content'):
                with TabPane('Existing', id='tab_existing'):
                    with Vertical():
                        yield Static('ID: N/A', id='sk_sketch_id')
                        yield Static('Anchor model: N/A', id='sk_anchor_model_path')
                        yield Static('Is processing:  N/A', id='sk_processing')
                        with Horizontal():
                            yield ListView(id='sketch_state_list_view')
                            yield Rule('vertical')
                            with Vertical():
                                yield Static('State id: N/A', id='sketch_state_id')
                                yield Static('State id: N/A', id='sketch_state_change')
                                yield Static(
                                    'Formalization status: N/A',
                                    id='sketch_state_frm_status',
                                )
                                yield Static('Error: N/A', id='sketch_state_error')
                                yield TextArea.code_editor(
                                    'N/A',
                                    language=None,
                                    id='sketch_state_iml',
                                    read_only=True,
                                )

                with TabPane('Create new', id='tab_new'):
                    with Vertical():
                        yield Static('Select anchor model:')
                        yield Select([])  # TODO: populate this
                        yield Input('Name')
                        yield Button('Create sketch', id='btn_create_sketch')

        yield Footer()

    @on(ListView.Highlighted, '#sketch_state_list_view')
    def on_sketch_state_highlighted(self):
        idx = self.query_one('#sketch_state_list_view', ListView).index
        if idx is not None and self.selected_sketch is not None:
            self.selected_sketch_state = self.selected_sketch.get_state_by_idx(idx)

    @on(ListView.Highlighted, '#sketch_list_view')
    def on_list_view_highlighted(self, event: ListView.Highlighted):
        """An existing sketch has been selected from this"""
        if self.sketch_container is not None:
            idx = self.query_one('#sketch_list_view', ListView).index
            sketches = list(self.sketch_container.sketches.values())
            self.selected_sketch = maybe(sketches.__getitem__, idx)

    @on(Button.Pressed, '#btn_create_sketch')
    def on_create_sketch(self):
        """ """
        pass


class TestSketchesApp(App):
    """
    Minimalist setup to test out Sketches screen
    """

    SCREENS = {'sketches': SketchScreen}

    def __init__(self, sk):
        super().__init__()
        self.sk = sk

    def compose(self):
        yield SketchScreen()

    def on_mount(self):
        self.push_screen('sketches')


if __name__ == '__main__':
    import json

    with open('src/codelogician/data/sketches/sketch1.json') as inFile:
        j = json.load(inFile)
        sketchC = SketchContainer.fromJSON(j)

    app = TestSketchesApp(sketchC)
    app.run()
