from lib.db import Steps
from ui.connector_step_editor import Connector_Step_Editor
from ui.editor import Editor
from ui.helpers import replace_widget
from ui.leak_step_editor import Leak_Step_Editor
from ui.print_step_editor import Print_Step_Editor
from ui.resistance_step_editor import Resistance_Step_Editor
from ui.vision_step_editor import Vision_Step_Editor


class Recipe_Spec_And_Step_Editor(Editor):
    def __init__(self, cell_widget=None, unsupported_steps=None):
        super().__init__(cell_widget=cell_widget)
        self.map = {
            "connector": {
                "type": "connector",
                "enable": self.connector_enabled_cb,
                "widget": "connector_editor_w",
                "editor": Connector_Step_Editor(),
                "tab": self.connector_t,
            },
            "barcodes": {
                "type": "barcodes",
                "enable": self.barcode_enabled_cb,
                "widget": "barcode_editor_w",
                # "editor": _Step_Editor(),
                "tab": self.barcode_t,
            },
            "resistance": {
                "type": "resistance",
                "enable": self.resistance_eabled_cb,
                "widget": "resistance_editor_w",
                "editor": Resistance_Step_Editor(),
                "tab": self.resistance_t,
            },
            "leak_1": {
                "type": "leak",
                "enable": self.leak_enabled_1_cb,
                "widget": "leak_editor_1_w",
                "editor": Leak_Step_Editor(),
                "tab": self.leak_1_t,
            },
            "leak_2": {
                "type": "leak",
                "enable": self.leak_eabled_2_cb,
                "widget": "leak_editor_2_w",
                "editor": Leak_Step_Editor(),
                "tab": self.leak_2_t,
                "hidden": True,
            },
            "vision": {
                "type": "vision",
                "enable": self.vision_enabled_cb,
                "widget": "vision_editor_w",
                "editor": Vision_Step_Editor(),
                "tab": self.vision_t,
            },
            "print": {
                "type": "print",
                "enable": self.print_enabled_cb,
                "widget": "print_editor_w",
                "editor": Print_Step_Editor(),
                "tab": self.print_t,
            },
        }
        for step_name in unsupported_steps:
            self.map.get(step_name, {})["hidden"] = True
        self.spec.update({step_name: map["enable"] for step_name, map in self.map.items()})
        for map in self.map.values():
            editor = map.get("editor", None)
            if editor is not None:
                replace_widget(self, map["widget"], editor)
            self.steps_tw.setTabVisible(self.steps_tw.indexOf(map["tab"]), not map.get("hidden", False))
        self.save_steps_b.clicked.connect(self.save_steps)
        self.reset_steps_b.clicked.connect(self.reset_steps)
        self.recipe_id = None

    def set_readonly(self, readonly=True):
        super().set_readonly(readonly=readonly)
        for map in self.map.values():
            editor = map.get("editor", None)
            if editor is not None:
                editor.set_readonly(readonly=readonly)
        self.save_steps_b.setDisabled(readonly)

    def do_autocomplete(self, autocomplete):
        if autocomplete is None:
            return
        step_editors_autocomplete = autocomplete.get("step_editors", None)
        super().do_autocomplete(autocomplete)
        if step_editors_autocomplete is not None:
            for step_name, map in self.map.items():
                editor = map.get("editor", None)
                if editor is not None:
                    editor.do_autocomplete(step_editors_autocomplete.get(step_name, None))

    def init(self):
        self.get_steps()

    def showing_dialog(self):
        self.reset_steps()

    # def connect_modified(self, check_modified):
    #     super().connect_modified(check_modified)
    #     # for map in self.map.values():
    #     #     editor = map.get("editor", None)
    #     #     if editor is not None:
    #     #         editor.connect_modified(self.check_modified)

    def render(self, data, field_name=None, row_number=None, crud=None):
        super().render(data, field_name=field_name, row_number=row_number, crud=crud)
        self.get_steps(available_steps=data.get("available_steps", {}))
        steps = set(data.get("steps", set()))
        for map in self.map.values():
            step = map.get("step", None)
            if step is not None:
                map["enable"].setChecked(step.name in steps and not map.get("hidden", False))
        self.render_steps()

    def parse(self, row_number=None, crud=None):
        ret = super().parse(row_number=row_number, crud=crud)
        ret["steps"] = []
        ret["available_steps"] = {}
        for step_name, map in self.map.items():
            ret["available_steps"][step_name] = map["step"].name
            if map["enable"].isChecked() and not map.get("hidden", False):
                ret["steps"].append(map["step"].name)
        return ret

    def get_steps(self, available_steps=None):
        if available_steps is None:
            available_steps = {}
        for step_name, map in self.map.items():
            if step_name in available_steps:
                map["step"] = Steps.get_by_id(available_steps[step_name])
            elif map.get("step", None) is None:
                map["step"] = Steps(type=map["type"], spec={})

    def render_steps(self):
        for step_name, map in self.map.items():
            step = map.get("step", None)
            if step is not None:
                editor = map.get("editor", None)
                if editor is not None:
                    editor.render(step.spec)

    def reset_steps(self):
        self.get_steps()
        self.render_steps()

    def save_steps(self):
        for map in self.map.values():
            step = map.get("step", None)
            if step is not None:
                editor = map.get("editor", None)
                if editor is not None:
                    step.spec = editor.parse()
                step.save()
        self.reset_steps()
