from user import User
from structures import Data_Structures as ds
from tkinter import simpledialog
from tkinter import *
from PIL import ImageTk, Image

class MyDialog(simpledialog.Dialog):

    def body(self, master):
        Label(master, text="Find:").grid(row=0)
        Label(master, text="Replace:").grid(row=1)

        self.e1 = Entry(master)
        self.e2 = Entry(master)

        self.e1.grid(row=0, column=1)
        self.e2.grid(row=1, column=1)
        return self.e1 # initial focus

    def apply(self):
        first = self.e1.get()
        second = self.e2.get()
        self.result = (first, second)

class Visual:

    def __init__(self, app, type, structure):
        self.app = app
        self.canvas = app.canvas
        self.root = app.root
        self.structure = structure
        self.type = type
        self.type_menu()

    def type_menu(self, event = None):
        self.app.empty_canvas()

        self.app.make_anim()

        if self.type == 'S':
            self.stack_menu()

        elif self.type == 'L':
            self.linkedlist_menu()

        else:  # type == 'T'
            self.tree_menu()

    def draw_stack(self, width, posX, posY, structure):
        loc_width1, loc_width2 = width/8, width/14
        self.canvas.create_rectangle(posX, posY + (width - loc_width1), posX + width, posY + width, fill="#ff5c74")
        self.canvas.create_rectangle(posX + (width/2) - loc_width2, posY, posX + (width/2) + loc_width2, posY + (width - loc_width1), fill="#ff5c74")

        colors = ["red", "blue", "magenta", "forestgreen"]

        dif = int((width//2) // 10)
        gap = int((posY - posY + width - loc_width1) // 8)

        for count, value in enumerate(structure):
            x, y = posX + (count + 1) * dif, (posY + width - loc_width1) - (count + 1) * gap
            xfin, yfin = 2*posX + width - x, y + (gap//1.27)
            self.last_stack_item = self.canvas.create_rectangle(x, y, xfin, yfin, fill=colors[0], outline=self.highlight, width=self.outline)

            if (self.highlight == 'yellow'):
                self.outline = 2
                self.highlight = 'lightgray'

            xmid, ymid = posX + (width//2), y + ((gap//1.27)//2)
            fnt = 'arial 15'
            self.last_stack_text = self.canvas.create_text(xmid, ymid, text=value, font=fnt)

            colors.append(colors.pop(0))

        self.canvas.pack()

    def stack_menu(self):
        self.highlight = 'lightgray'
        self.outline = 2

        cover = ImageTk.PhotoImage(Image.open('images/stack.png'))
        self.canvas.create_image(550, 400, image=cover)

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(550, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.app.user_main_window)

        replace_img = ImageTk.PhotoImage(Image.open('images/replace.png'))
        replace_btn = self.canvas.create_image(550, 600, image=replace_img)
        self.canvas.tag_bind(replace_btn, '<Button-1>', self.pre_replace_stack)

        sortup_img = ImageTk.PhotoImage(Image.open('images/sortasc.png'))
        sortup_btn = self.canvas.create_image(300, 600, image=sortup_img)
        self.canvas.tag_bind(sortup_btn, '<Button-1>', self.pre_asc_stack)

        sortdown_img = ImageTk.PhotoImage(Image.open('images/sortdsc.png'))
        sortdown_btn = self.canvas.create_image(800, 600, image=sortdown_img)
        self.canvas.tag_bind(sortdown_btn, '<Button-1>', self.pre_dsc_stack)

        self.canvas.pack()
        self.canvas.mainloop()

    def pre_replace_stack(self, event = None):
        self.fStack = self.structure.copy()
        self.sStack = []
        self.done = False

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.replace_stack()

    def replace_stack(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_stack_replace)

        self.draw_stack(450, 75, 150, self.fStack)
        self.draw_stack(450, 575, 150, self.sStack)

        if (len(self.sStack) > 0 and self.sStack[-1] == self.find):
            self.canvas.itemconfig(self.last_stack_item, outline='yellow', width=4)
            self.canvas.itemconfig(self.last_stack_text, text=self.replace)
            self.sStack[-1] = self.replace

        self.canvas.pack()
        self.canvas.mainloop()

    def next_stack_replace(self, event = None):
        if (len(self.fStack) == 0):
            self.done = True

        if (len(self.fStack) > 0 and self.done is False):
            self.sStack.append(self.fStack.pop())
            self.replace_stack()

        if (self.done and len(self.sStack) > 0):
            self.fStack.append(self.sStack.pop())
            self.replace_stack()

    def pre_asc_stack(self, event = None):
        self.fStack = self.structure.copy()
        self.sStack = []
        self.tStack = []
        self.done = False
        self.push = False
        self.found_local = False

        self.sort_asc_stack()

    def sort_asc_stack(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_stack_asc)

        self.draw_stack(300, 50, 200, self.fStack)
        self.draw_stack(300, 400, 200, self.sStack)
        self.draw_stack(300, 750, 200, self.tStack)

        self.canvas.pack()
        self.canvas.mainloop()

    def next_stack_asc(self, event = None):
        if not self.done:
            if (self.tStack == sorted(self.structure)[::-1]):
                self.done = True
                while self.tStack:
                    self.fStack.append(self.tStack.pop())
                self.sort_asc_stack()

            if (self.fStack == [] and self.sStack != []):
                self.found_local = True
                while self.sStack:
                    self.fStack.append(self.sStack.pop())
                self.sort_asc_stack()

            if (self.push is False):
                self.push = True
                if (self.fStack != []):
                    self.sStack.append(self.fStack.pop())

                if (self.fStack == []):
                    if (len(self.sStack) == 1 and len(self.tStack) != 0):
                        if (self.sStack[-1] > self.tStack[-1]):
                            tmp = self.sStack.pop()
                            self.sStack.append(self.tStack.pop())
                            self.tStack.append(tmp)
                        else:
                            self.tStack.append(self.sStack.pop())
                        self.sort_asc_stack()

            else:
                change = False
                self.push = False

                if (self.fStack == []):
                    if (len(self.sStack) == 1 and len(self.tStack) != 0 and self.sStack[-1] > self.tStack[-1]):
                        tmp = self.sStack.pop()
                        self.sStack.append(self.tStack.pop())
                        self.tStack.append(tmp)
                        self.sort_asc_stack()


                if (self.tStack == []):
                    self.tStack.append(self.sStack.pop())
                    change = True

                else:
                    if (self.found_local and self.sStack != []):
                        self.tStack.append(self.sStack.pop())
                        self.found_local = False
                        change = True

                    if (self.sStack != [] and not change):
                        if (self.sStack[-1] > self.tStack[-1]):
                            tmp = self.sStack.pop()
                            self.sStack.append(self.tStack.pop())
                            self.tStack.append(tmp)
                            change = True

                if not change:
                    self.next_stack_asc()

            self.sort_asc_stack()

    def pre_dsc_stack(self, event = None):
        self.fStack = self.structure.copy()
        self.sStack = []
        self.tStack = []
        self.done = False
        self.push = False
        self.found_local = False

        self.sort_dsc_stack()

    def sort_dsc_stack(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_stack_dsc)

        self.draw_stack(300, 50, 200, self.fStack)
        self.draw_stack(300, 400, 200, self.sStack)
        self.draw_stack(300, 750, 200, self.tStack)

        self.canvas.pack()
        self.canvas.mainloop()

    def next_stack_dsc(self, event = None):
        if not self.done:
            if (self.tStack == sorted(self.structure)):
                self.done = True
                while self.tStack:
                    self.fStack.append(self.tStack.pop())
                self.sort_dsc_stack()

            if (self.fStack == [] and self.sStack != []):
                self.found_local = True
                while self.sStack:
                    self.fStack.append(self.sStack.pop())
                self.sort_dsc_stack()

            if (self.push is False):
                self.push = True
                if (self.fStack != []):
                    self.sStack.append(self.fStack.pop())

                if (self.fStack == []):
                    if (len(self.sStack) != 0 and len(self.tStack) != 0):
                        if (self.sStack[-1] < self.tStack[-1]):
                            tmp = self.sStack.pop()
                            self.sStack.append(self.tStack.pop())
                            self.tStack.append(tmp)
                        else:
                            self.tStack.append(self.sStack.pop())
                        self.sort_dsc_stack()

            else:
                change = False
                self.push = False

                if (self.fStack == []):
                    if (len(self.sStack) != 0 and len(self.tStack) != 0 and self.sStack[-1] < self.tStack[-1]):
                        tmp = self.sStack.pop()
                        self.sStack.append(self.tStack.pop())
                        self.tStack.append(tmp)
                        self.sort_dsc_stack()

                if (self.tStack == []):
                    self.tStack.append(self.sStack.pop())
                    change = True

                else:
                    if (self.found_local and self.sStack != []):
                        self.tStack.append(self.sStack.pop())
                        self.found_local = False
                        change = True

                    if (self.sStack != [] and not change):
                        if (self.sStack[-1] < self.tStack[-1]):
                            tmp = self.sStack.pop()
                            self.sStack.append(self.tStack.pop())
                            self.tStack.append(tmp)
                            change = True

                if not change:
                    self.next_stack_dsc()

            self.sort_dsc_stack()

############################################################################################

    def linkedlist_menu(self):

        cover = ImageTk.PhotoImage(Image.open('images/linkedlist.png'))
        self.canvas.create_image(550, 400, image=cover)

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(550, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.app.user_main_window)

        replace_img = ImageTk.PhotoImage(Image.open('images/replace.png'))
        replace_btn = self.canvas.create_image(250, 650, image=replace_img)
        self.canvas.tag_bind(replace_btn, '<Button-1>', self.pre_replace_linkedlist)

        insertsort_img = ImageTk.PhotoImage(Image.open('images/insertsort.png'))
        insertsort_btn = self.canvas.create_image(650, 650, image=insertsort_img)
        self.canvas.tag_bind(insertsort_btn, '<Button-1>', self.pre_insertion_sort)

        bubsort_img = ImageTk.PhotoImage(Image.open('images/bubsort.png'))
        bubsort_btn = self.canvas.create_image(850, 650, image=bubsort_img)
        self.canvas.tag_bind(bubsort_btn, '<Button-1>', self.pre_bubble_sort)

        selsort_img = ImageTk.PhotoImage(Image.open('images/selsort.png'))
        selsort_btn = self.canvas.create_image(450, 650, image=selsort_img)
        self.canvas.tag_bind(selsort_btn, '<Button-1>', self.pre_selection_sort)

        self.canvas.pack()
        self.canvas.mainloop()

    def draw_linkedlist(self, structure):
        self.linkedlist_nodes = []
        self.canvas.create_text(120,340, text="Front", font='arial 16')

        x, y = 80, 360
        for item in structure[:-1]:
            self.draw_linkedlist_box(x, y, item)
            x += 120
        self.draw_linkedlist_box(x, y, structure[-1], True)

        self.canvas.pack()

    def draw_linkedlist_box(self, x, y, data, end=False):
        node = self.canvas.create_rectangle(x, y, x+80, y+80, width=3, fill="white", outline="lightgray")
        txt = self.canvas.create_text(x+40,y+40, text=data, font='arial 16')
        self.linkedlist_nodes.append((node, txt))

        if (not end):
            self.canvas.create_line(x+80, y+40, x+122, y+40, width=5, fill="red")
            self.canvas.create_line(x+100, y+10, x+120, y+40, width=5, fill="red")
            self.canvas.create_line(x + 100, y+70, x + 120, y+40, width=5, fill="red")

    def pre_replace_linkedlist(self, event = None):
        self.linkedlist_pos = 0

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.replace_linkedlist()

    def replace_linkedlist(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_linkedlist_replace)

        self.draw_linkedlist(self.structure)
        self.canvas.itemconfig(self.linkedlist_nodes[self.linkedlist_pos][0], outline='red')

        self.canvas.pack()
        self.canvas.mainloop()

    def next_linkedlist_replace(self, event = None):
        if (self.linkedlist_pos < len(self.structure)):
            if (self.structure[self.linkedlist_pos] == self.find):
                self.structure[self.linkedlist_pos] = self.replace
            else:
                self.linkedlist_pos += 1

            if (self.linkedlist_pos < len(self.structure)):
                self.replace_linkedlist()

    def pre_selection_sort(self, event = None):
        self.pos, self.left = 0, 0
        self.minimum = 0
        self.done = False
        self.selection_sort()

    def selection_sort(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_selection_sort)

        self.draw_linkedlist(self.structure)

        if (self.done is False):
            self.canvas.itemconfig(self.linkedlist_nodes[self.left][0], outline='red')
            self.canvas.itemconfig(self.linkedlist_nodes[self.minimum][0], fill='lightgreen')
            if (len(self.structure) > 1):
                self.canvas.itemconfig(self.linkedlist_nodes[self.pos][0], outline='blue', fill='yellow')

        self.canvas.pack()
        self.canvas.mainloop()

    def next_selection_sort(self, event = None):
        if self.done is False:
            self.pos += 1

            if (self.pos < len(self.structure)):
                if (self.minimum is None or self.structure[self.pos] < self.structure[self.minimum]):
                    self.minimum = self.pos
            else:
                self.structure[self.left], self.structure[self.minimum] = self.structure[self.minimum], self.structure[self.left]
                self.left += 1
                self.minimum = self.left
                self.pos = self.left

                if (self.left == len(self.structure)):
                    self.done = True
            self.selection_sort()

    def pre_bubble_sort(self, event = None):
        self.left, self.right = 0, 1
        self.done = False
        self.swap = False
        self.bubble_sort()

        if (len(self.structure) < 2):
            self.done = True

    def bubble_sort(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_bubble_sort)

        self.draw_linkedlist(self.structure)

        if (self.done is False):
            self.canvas.itemconfig(self.linkedlist_nodes[self.left][0], fill='yellow')
            self.canvas.itemconfig(self.linkedlist_nodes[self.right][0], fill='yellow')

        if (self.swap):
            self.canvas.itemconfig(self.linkedlist_nodes[self.left-1][1], fill='red')
            self.canvas.itemconfig(self.linkedlist_nodes[self.right-1][1], fill='red')
            self.swap = False

        self.canvas.pack()
        self.canvas.mainloop()

    def next_bubble_sort(self, event = None):
        if self.done is False:

            if (self.structure[self.right] < self.structure[self.left]):
                self.structure[self.right], self.structure[self.left] = self.structure[self.left], self.structure[self.right]
                self.swap = True

            self.left += 1
            self.right += 1
            if (self.right == len(self.structure)):
                self.left, self.right = 0, 1

                if (self.structure == sorted(self.structure)):
                    self.done = True

            self.bubble_sort()

    def pre_insertion_sort(self, event = None):
        self.pos, self.left = 0, 0
        self.done = False
        self.swap = False
        self.insertion_sort()

    def insertion_sort(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_insertion_sort)

        self.draw_linkedlist(self.structure)

        if (self.done is False):
            self.canvas.itemconfig(self.linkedlist_nodes[self.left][0], outline='red',  fill='lightgreen')
            if (len(self.structure) > 1):
                self.canvas.itemconfig(self.linkedlist_nodes[self.pos][0], outline='blue', fill='yellow')

        if (self.swap):
            self.canvas.itemconfig(self.linkedlist_nodes[self.left][1], fill='red')
            self.canvas.itemconfig(self.linkedlist_nodes[self.pos][1], fill='red')
            self.swap = False

        self.canvas.pack()
        self.canvas.mainloop()

    def next_insertion_sort(self, event = None):
        if self.done is False:
            self.pos += 1

            if (self.pos == len(self.structure)):
                self.left += 1
                self.pos = self.left

                if (self.left == len(self.structure)):
                    self.done = True

            else:
                if (self.structure[self.left] > self.structure[self.pos]):
                    self.structure[self.left], self.structure[self.pos] = self.structure[self.pos], self.structure[self.left]
                    self.swap = True

            self.insertion_sort()

############################################################################################

    def tree_menu(self):
        self.tree_root = self.structure.root
        self.tree_canvas = dict()

        cover = ImageTk.PhotoImage(Image.open('images/tree.png'))
        self.canvas.create_image(550, 400, image=cover)

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(550, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.app.user_main_window)

        level_img = ImageTk.PhotoImage(Image.open('images/level.png'))
        level_btn = self.canvas.create_image(250, 650, image=level_img)
        self.canvas.tag_bind(level_btn, '<Button-1>', self.pre_replace_tree)

        inorder_img = ImageTk.PhotoImage(Image.open('images/inorder.png'))
        inorder_btn = self.canvas.create_image(450, 650, image=inorder_img)
        self.canvas.tag_bind(inorder_btn, '<Button-1>', self.pre_replace_tree_inorder)

        postorder_img = ImageTk.PhotoImage(Image.open('images/postorder.png'))
        postorder_btn = self.canvas.create_image(650, 650, image=postorder_img)
        self.canvas.tag_bind(postorder_btn, '<Button-1>', self.pre_replace_tree_postorder)

        preorder_img = ImageTk.PhotoImage(Image.open('images/preorder.png'))
        preorder_btn = self.canvas.create_image(850, 650, image=preorder_img)
        self.canvas.tag_bind(preorder_btn, '<Button-1>', self.pre_replace_tree_preorder)

        self.canvas.pack()
        self.canvas.mainloop()

    def draw_binarytree(self, event = None):
        self.canvas.create_text(550,50, text="Tree Root", font = 'arial 20')

        self.draw_tree_nodes(self.tree_root)

        self.canvas.pack()

    def draw_tree_nodes(self, node : ds.Node, parent : ds.Node = None, create = False):
        x, y = node.pos
        level = node.level
        data = node.data

        oval = self.canvas.create_oval(x, y, x+80, y+80, width=3, fill="white",)
        txt = self.canvas.create_text(x+40, y+40, text=data, font='arial 15', fill="deepskyblue")

        self.tree_canvas[node.pos] = (oval, txt)

        if parent is not None:
            parX, parY = parent.pos
            self.canvas.create_line(x+40, y, parX+40, parY+80, width=3, fill="white")

        if (level + 1 <= 4):
            if (node.left is not None):
                self.draw_tree_nodes(node.left, node, create)

            if (node.right is not None):
                self.draw_tree_nodes(node.right, node, create)

    def pre_replace_tree(self, event = None):
        self.highlight = self.tree_root
        self.level = [self.tree_root]
        self.next_level = []
        self.done = False

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.replace_tree()

        # self.draw_binarytree()
        #
        # self.canvas.pack()
        # self.canvas.mainloop()

    def replace_tree(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_tree_replace)

        self.draw_binarytree()
        self.canvas.itemconfig(self.tree_canvas[self.highlight.pos][0], outline='red')

        self.canvas.pack()
        self.canvas.mainloop()

    def next_tree_replace(self, event = None):
        if self.done is False:
            if (self.level == []):
                if (self.next_level == []):
                    self.done = True
                    self.highlight = self.tree_root
                    self.replace_tree()

                else:
                    self.level = self.next_level[:]
                    self.next_level = []

            if (self.level != []):
                node = self.level.pop()

                if (node.left is not None):
                    self.next_level.append(node.left)

                if (node.right is not None):
                    self.next_level.append(node.right)

                self.highlight = node
                if (node.data == self.find):
                    node.data = self.replace
            else:
                self.done = True
                self.highlight = self.tree_root

            self.replace_tree()

    def pre_replace_tree_inorder(self, event = None):
        self.order = self.get_inorder()
        self.highlight = self.order[0]
        self.done = False
        self.replaced = False

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.tree_replace_order()

    def pre_replace_tree_postorder(self, event = None):
        self.order = self.get_postorder()
        self.highlight = self.order[0]
        self.done = False
        self.replaced = False

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.tree_replace_order()

    def pre_replace_tree_preorder(self, event = None):
        self.order = self.get_preorder()
        self.highlight = self.order[0]
        self.done = False
        self.replaced = False

        d = MyDialog(self.root)
        self.find, self.replace = d.result

        if (self.find != '' and self.replace != ''):
            self.tree_replace_order()

    def tree_replace_order(self, event = None):
        self.app.empty_canvas()

        exit_img = ImageTk.PhotoImage(Image.open('images/exit_sm.png'))
        ex_btn = self.canvas.create_image(1020, 750, image=exit_img)
        self.canvas.tag_bind(ex_btn, '<Button-1>', self.type_menu)

        next_img = ImageTk.PhotoImage(Image.open('images/next.png'))
        next_btn = self.canvas.create_image(800, 750, image=next_img)
        self.canvas.tag_bind(next_btn, '<Button-1>', self.next_order)

        self.draw_binarytree()
        self.canvas.itemconfig(self.tree_canvas[self.highlight.pos][0], outline='red')

        self.canvas.pack()
        self.canvas.mainloop()

    def next_order(self, event = None):
        if (self.done is False):
            if not self.replaced:
                if (len(self.order) == 0):
                    self.done = True
                    self.highlight = self.tree_root

                else:
                    node = self.order.pop(0)
                    self.highlight = node
                    if (node.data == self.find):
                        self.replaced = True
            else:
                self.replaced = False
                self.highlight.data = self.replace
                self.canvas.itemconfig(self.tree_canvas[self.highlight.pos][1], text = self.replace)

            self.tree_replace_order()

    def get_inorder(self):
        res = []
        def inorder(node):
            if (node.left is not None):
                inorder(node.left)

            res.append(node)

            if (node.right is not None):
                inorder(node.right)

        inorder(self.tree_root)
        return res

    def get_postorder(self):
        res = []
        def post(node):
            if (node.left is not None):
                post(node.left)

            if (node.right is not None):
                post(node.right)

            res.append(node)

        post(self.tree_root)
        return res

    def get_preorder(self):
        res = []
        def post(node):
            res.append(node)

            if (node.left is not None):
                post(node.left)

            if (node.right is not None):
                post(node.right)

        post(self.tree_root)
        return res
