
import posixpath
import tkinter as tk
import tkinter.ttk as ttk
from source.packages import PackageManager
from direct.showbase.ShowBase import ShowBase
from panda3d.core import VirtualFileSystem, Material
from direct.stdpy.file import walk

import simplepbr
import gltf

def get_icons():
    return type('', (object,), {
        'app': tk.PhotoImage(file="icons/application.png"),
        'brick': tk.PhotoImage(file="icons/brick.png"),
        'bricks': tk.PhotoImage(file="icons/bricks.png"),
        'computer': tk.PhotoImage(file="icons/computer.png"),
        'folder': tk.PhotoImage(file="icons/folder.png"),
        'shape_group': tk.PhotoImage(file="icons/shape_group.png"),
        'pictures': tk.PhotoImage(file="icons/pictures.png"),
        'picture': tk.PhotoImage(file='icons/picture.png'),
        "page_red": tk.PhotoImage(file='icons/page_red.png'),
        'shape_square': tk.PhotoImage(file='icons/shape_square.png'),
        'color_wheel': tk.PhotoImage(file='icons/color_wheel.png'),
        'color_swatch': tk.PhotoImage(file='icons/color_swatch.png')
    })()

class PandaApp(ShowBase):
    def __init__(self, fStartDirect=True, windowType=None):
        super().__init__(fStartDirect, windowType)

running = True
def on_tk_closed():
    global running
    running = False

def add_package_contents_to_tree(tree, package, type, name, extensions, icon_folder, icon_group, icon_item):
    data_path = posixpath.join(package.mount_dir, type)
    tree.insert(package.mount_dir, 'end', data_path, text=f' {name}', image=icon_group)
    file_count = 0
    for root, paths, files in walk(data_path):
        for path in paths:
            tree.insert(root, 'end', posixpath.join(root, path), text=f' {path}', image=icon_folder)
        for file in files:
            if file.lower().endswith(extensions):
                file_count += 1
                tree.insert(root, 'end', posixpath.join(root, file), text=f' {file}', image=icon_item)
    tree.item(data_path, text=f' {name} ({file_count})')

def add_package_models_to_tree(tree, package, icons):
    add_package_contents_to_tree(tree, package, 'models/', '3D Models', ('.glb', '.gltf', '.obj', '.egg'), icons.folder, icons.shape_group, icons.shape_square)

def add_package_textures_to_tree(tree, package, icons):
    add_package_contents_to_tree(tree, package, 'textures/', 'Image Textures', ('.png', '.jpg', '.bmp'), icons.folder, icons.pictures, icons.picture)

def add_package_materials_to_tree(tree, package, icons):
    add_package_contents_to_tree(tree, package, 'materials/', 'Materials', ('.json'), icons.folder, icons.color_wheel, icons.color_swatch)

def add_package_to_tree(tree, package, icons):
    add_package_models_to_tree(tree, package, icons)
    add_package_textures_to_tree(tree, package, icons)
    add_package_materials_to_tree(tree, package, icons)

def create_tk_treeview(parent, packages, icons):
    tree = ttk.Treeview(parent, show="tree")
    tree.insert('', 'end', '/', text=' /', open=True, image=icons.app)
    tree.insert('/', 'end', '/main/', text=f' Main Package "{packages.main_package.meta.name}" - {packages.main_package.meta.version}', image=icons.computer)
    tree.insert('/', 'end', '/include/', text=f' Included Packages ({len(packages.package_list)})', image=icons.bricks)
    add_package_to_tree(tree, packages.main_package, icons)
    for package in packages.package_list:
        tree.insert('/include/', 'end', package.mount_dir, text=f' "{package.meta.name}" - {package.meta.version}', image=icons.brick)
        add_package_to_tree(tree, package, icons)
    #tree.pack(fill='x')
    return tree

class TreeEvents:
    def __init__(self, tree, panda):
        self.tree = tree
        self.panda = panda
        self.tree.bind('<Double-1>', self.on_double_click)
        self.nodes = []

    def on_double_click(self, event):
        item = self.tree.selection()[0]
        if item.lower().endswith(('.glb', '.gltf', '.obj', '.egg')):
            mat = Material()
            mat.setAmbient((1, 0, 0, 1))
            node = self.panda.loader.loadModel(item)
            node.reparentTo(self.panda.render)
            node.setMaterial(mat)
            self.nodes.append(node)

def start_explorer(args):
    tk_app = tk.Tk()
    tk_app.geometry("700x500")
    tk_app.protocol('WM_DELETE_WINDOW', on_tk_closed)

    #tk_app = tk.Frame(tk_app, width=500)
    tk_app.grid_rowconfigure(0, weight=1)
    tk_app.grid_columnconfigure(0, weight=1)
    tk_app.grid_columnconfigure(1, weight=1)

    package_frame = tk.Frame(tk_app, highlightbackground="black", highlightthickness=1, padx=4, pady=4)
    package_frame.grid(column=0, row=0, sticky="news")
    package_frame.grid_columnconfigure(0, weight=1)
    package_frame.grid_rowconfigure(0, weight=1)
    package_frame.grid_rowconfigure(1, weight=1000)
    label1 = tk.Label(package_frame, text='Packages')
    label1.grid(row=0, column=0, sticky='n')

    scene_frame = tk.Frame(tk_app, highlightbackground="black", highlightthickness=1, padx=4, pady=4)
    scene_frame.grid(column=1, row=0, sticky="news")
    scene_frame.grid_columnconfigure(0, weight=1)
    scene_frame.grid_rowconfigure(0, weight=1)
    scene_frame.grid_rowconfigure(1, weight=10000)

    label2 = tk.Label(scene_frame, text='Scene Graph')
    label2.grid(row=0, column=0)

    scene_tree = ttk.Treeview(scene_frame)
    scene_tree.grid(row=1, column=0, sticky="news")

    panda_app = PandaApp()
    simplepbr.init()
    gltf.patch_loader(panda_app.loader) 

    packages = PackageManager(VirtualFileSystem.getGlobalPtr())
    packages.set_main_package(args.main)
    if args.package:
        for include in args.package:
            packages.include_package(include)

    icons = get_icons()
    tree = create_tk_treeview(package_frame, packages, icons)
    tree.grid(row=1, column=0, sticky="news")

    events = TreeEvents(tree, panda_app)

    try:
        while running:
            panda_app.taskMgr.step()
            tk_app.update_idletasks()
            tk_app.update()
    except KeyboardInterrupt as stop:
        pass

    '''
    window = tk.Tk()
    icons = get_icons()

    fs = PackageManager(VirtualFileSystem.getGlobalPtr())
    fs.set_main_package('assets')

    mdls = fs.main_package.all_models()
    txts = fs.main_package.all_textures()
    print(mdls, txts, loader)

    menu = tk.Menu(window)
    menu.add_command(label="Exit", command=window.quit)
    window.config(menu=menu)

    mainframe = tk.Frame(window, borderwidth=5)
    mainframe.grid(column=0, row=0)
    mainframe.columnconfigure(0, weight=3)

    packageTree = ttk.Treeview(mainframe, show="tree")
    packageTree.insert('', 'end', '/', text=' Virtual FS', image=icons.app)
    packageTree.pack()

    window.mainloop()
    frame = tk.Frame(window, borderwidth=5)
    frame.pack()
    
    frame.columnconfigure(0, weight=1)
    frame.columnconfigure(1, weight=3)

    tree = ttk.Treeview(frame, show="tree")
    tree.grid(column=0, row=0, sticky=tk.NW)

    tree.insert('', 'end', '/', text=' Virtual Filesystem', open=True, image=icons.app)
    tree.insert('/', 'end', '/main/', text=' main/', image=icons.computer) 
    tree.insert('/main/', 'end', '/main/models/', text=' models/', image=icons.folder)
    tree.insert('/main/', 'end', '/main/textures/', text=' textures/', image=icons.folder)
    tree.insert('/', 'end', '/packages/', text=' packages/', image=icons.bricks)
    tree.insert('/packages/', 'end', '/packages/user-package-1/', text=' user-package-1/', image=icons.brick)
    tree.insert('/packages/', 'end', '/packages/user-package-2/', text=' user-package-2/', image=icons.brick)
    tree.insert('/packages/', 'end', '/packages/user-package-3/', text=' user-package-3/', image=icons.brick)

    window.mainloop()
    '''