from textual.app import App, ComposeResult
from textual.widgets import Footer, Tab, Tabs, Header
from textual import on, events

from textual_fspicker import FileOpen, FileSave, Filters

from ui.widgets.sidebar import Sidebar
from ui.widgets.timeline import Timeline, TimelineRow
from ui.widgets.project_settings import ProjectSettings
from ui.widgets.channel import Channel
from ui.widgets.context_menu import ContextMenu, NoSelectStatic

from project import ProjectChannel, Project, ChunkType
from ui.widgets.chunk_types.audio import AudioChunk, Chunk


class AppUI(App):    
    CSS_PATH = "../assets/style.tcss"
    
    def __init__(self, project):
        super().__init__()
        self.zoom_level = 0.05
        self.last_zoom_level = self.zoom_level
        self.project = project
        
        self.open_project_path = None
        self.first_tab_click = True # stupid events firing when the app is first composed :/
        
    @on(events.Key)
    async def key_pressed(self, event: events.Key):
        if event.key == "space":
            timeline = self.query_one(Timeline)
            if not timeline.song_player.paused:
                timeline.song_player.pause()
            else:
                timeline.song_player.play_project(self.app.project)
    
    def create_channel(self, name: str):
        new_project_channel = ProjectChannel(
            name
        )
        
        self.query_one("#channels").mount(Channel(
            len(self.project.channels),
            new_project_channel,
            name,
            
        ), before=-1)
        self.query_one("#rows").mount(TimelineRow(new_project_channel))
        
        self.project.channels.append(new_project_channel)
        
    def handle_menu_click(self, choice: str):
        # user clicked off the menu
        if choice == None: return 
        
        match choice:
            case "Save":
                if not self.open_project_path:
                    self.handle_menu_click("Save as") # just move it to save as
                    return
                    
                self.project.write_to_file(self.open_project_path)
                self.notify("Saved project.")
                
            case "Save as":
                def callback(path: str):
                    if path == None: return
                    self.open_project_path = path
                    self.project.write_to_file(path)
                    self.notify(f"Saved as \"{path}\"", title="Saved")
                
                self.push_screen(FileSave(
                    filters=Filters(
                        ("TerminalDAW Project File", lambda p: p.suffix.lower() == ".tdp"),
                        ("Any", lambda _: True)
                        
                    )
                ), callback=callback)
                
            case "Open":
                def callback(path: str):
                    if path == None: return
                    
                    self.project = Project.from_file(path)
                    self.open_project_path = path
                    
                    ### load all the ui elements
                    # sidebar channels
                    sidebar_channels = self.query_one("#channels")
                    
                    # we cant use sidebar_channels.remove_children() because that would
                    # also remove the "Add Channel" button
                    for child in sidebar_channels.children:
                        if child.id != "add-channel":
                            child.remove()
                            
                    for i, channel in enumerate(self.app.project.channels):
                        sidebar_channels.mount(Channel(
                            i,
                            channel,
                            channel.name,
                            channel.mute,
                            channel.solo,
                            channel.pan,
                            channel.volume
                        ), before=-1)
                        
                    # timeline tracks
                    timeline = self.query_one(Timeline)
                    rows = timeline.query_one("#rows")
                    
                    for channel in self.project.channels:
                        row = TimelineRow(channel)
                        
                            
                        row.styles.width = timeline.bar_offset * self.project.song_length
                        rows.mount(row)

                        for chunk in channel.chunks:
                            
                            if chunk.chunk_type == ChunkType.CHUNK:
                                row.mount(Chunk(chunk_name=chunk.name, bar_pos=chunk.position))
                            elif chunk.chunk_type == ChunkType.AUDIO:
                                row.mount(AudioChunk(chunk.audio_data, chunk.sample_rate, chunk.name, chunk.position))
                                
                    
                    self.notify(f"Loaded \"{path}\"")
                    
                self.push_screen(FileOpen(
                    filters=Filters(
                        ("TerminalDAW Project File", lambda p: p.suffix.lower() == ".tdp"),
                        ("Any", lambda _: True)
                        
                    )
                ), callback=callback)
                
            case _:
                self.notify("Sorry, that isn't implemented yet... ;-;", severity="warning")
        
    @on(Tabs.TabActivated)
    async def top_menu_tab_clicked(self, event: Tabs.TabActivated):
        if self.first_tab_click:
            event.tabs.active = None
            self.first_tab_click = False
            return
        
        options = {
            "File": [
                "Save",
                "Save as",
                "Open",
                "Render",
                "Settings"
            ],
            "Edit": [
                "Copy",
                "Paste",
                "Cut"
            ],
            "About": [
                "Chookspace repo",
                "Copyright"
            ]
        }
        
        self.app.push_screen(ContextMenu(options[event.tab.label], self.app.mouse_position + (0, 1)), callback=self.handle_menu_click)
    
    def compose(self) -> ComposeResult:
        yield Tabs(
            Tab("File"),
            Tab("Edit"),
            Tab("About"),
        id="top-menu")
        yield Sidebar()
        yield Timeline()
        yield ProjectSettings()
        yield Footer()