# -*- coding: UTF-8 -*-
# 作者：huanhuilong
# 标题：Python Tkinter 开发应用
# 描述：设计GUI组件


from tkinter import Tk, Button
from tkinter import messagebox
from abc import ABC, abstractclassmethod


class Component:
    def __init__(self, app) -> None:
        self.app = app

    @abstractclassmethod
    def component_did_mount(self, *args):
        pass

    @abstractclassmethod
    def component_did_unmount(self):
        pass

    @abstractclassmethod
    def render(self):
        pass


class About(Component):
    def __init__(self, app) -> None:
        super().__init__(app)
        self.root = None
        self.btn = None

    def component_did_mount(self, root):
        self.root = root

    def component_did_unmount(self):
        self.root = None

    def render(self):
        messagebox.showinfo("关于我", "python.csdn.net")


class Home(Component):
    def __init__(self, app) -> None:
        super().__init__(app)
        self.app = app
        self.root = None
        self.btn = None

    def component_did_mount(self):
        self.text = "关于我"

    def component_did_unmount(self):
        self.root = None

    def render(self):
        self.root = Tk()
        self.btn = Button(
            self.root,
            text=self.text,
            command=lambda: self.app.navigate_to('About')
        )
        self.btn.pack()
        self.root.mainloop()


class App:
    def __init__(self, component_constructors) -> None:
        self.root = None
        self.component_constructors = component_constructors
        self.components = {}
        self.stack = []

    def init(self):
        for name in self.component_constructors:
            component_constructor = self.component_constructors[name]
            self.components[name] = component_constructor(self)

    def navigate_to(self, name, *args):
        if self.components.get(name) is None:
            return
        c = self.components[name]
        self.stack.append(c)
        if name == 'About':
            c.component_did_mount(self.root)
        elif name == "Home":
            c.component_did_mount()
        c.render()

    def go_back(self):
        if len(self.stack) == 0:
            return
        c = self.stack.pop()
        c.component_did_unmount()

    def render(self):
        if len(self.stack) > 0:
            return
        self.navigate_to("Home", self.root)


if __name__ == '__main__':
    app = App({
        "Home": Home,
        "About": About,
    })
    app.init()
    app.render()
