//- sixten: Views
inline workspace_view *W_CreateNewView(workspace_view_type Type, workspace_panel *Parent)
{
    memory_arena *Arena = ArenaAllocate(Gigabytes(1));
    workspace_view *View = PushStruct(Arena, workspace_view);
    View->Arena = Arena;
    View->Type = Type;
    View->Parent = Parent;
    
    switch(View->Type)
    {
        case W_View_Editor:
        {
            View->Data = PushStruct(View->Arena, workspace_view_editor);
        } break;
        
        case W_View_CommandPalette:
        {
            View->Data = PushStruct(View->Arena, workspace_view_command_palette);
        } break;
        
        case W_View_Settings:
        {
            View->Data = PushStruct(View->Arena, workspace_view_settings);
        } break;
        
        case W_View_TextEditor:
        {
            View->Data = PushStruct(View->Arena, workspace_view_text_editor);
            
            workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
            Editor->ProcessingArena = ArenaAllocate(Gigabytes(1));
            Editor->Text = MutableStringAllocate(Gigabytes(1));
            Editor->HistoryArena = ArenaAllocate(Gigabytes(1));
            
            SenDLLInit(&Editor->History.Sentinel);
            Editor->History.At = &Editor->History.Sentinel;
            Editor->SavePoint = Editor->History.At;
            
            workspace_text_data TextData = W_TextDataFromString(Editor->ProcessingArena, Editor->Text.String);
            Editor->Tokens = TextData.Tokens;
            Editor->Lines = TextData.Lines;
        } break;
        
        case W_View_CharacterEditor:
        {
            View->Data = PushStruct(View->Arena, workspace_view_character_editor);
        } break;
        
        default: break;
    }
    
    DLLInsertLast(Parent->FirstView, Parent->LastView, View);
    
    if(View->Parent)
    {
        Parent->CurrentView = View;
    }
    
    return(View);
}

inline void W_DestroyView(workspace_view *View)
{
    switch(View->Type)
    {
        case W_View_TextEditor:
        {
            workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
            ArenaRelease(Editor->ProcessingArena);
            MutableStringRelease(&Editor->Text);
            ArenaRelease(Editor->HistoryArena);
        } break;
        
        default: break;
    }
    
    // sixten(NOTE): This function does not ensure that the view is not being used anywhere else.
    ArenaRelease(View->Arena);
}

inline b32 W_ViewIsCurrent(workspace_view *View)
{
    workspace *Workspace = W_GetState();
    
    b32 Result = (Workspace->CurrentPanel && Workspace->CurrentPanel->CurrentView == View);
    return(Result);
}

inline string W_GetViewName(workspace_view *View)
{
    string Result = StrLit("Unnamed view");
    switch(View->Type)
    {
        case W_View_Startup: { Result = StrLit("Welcome"); } break;
        case W_View_Editor: { Result = StrLit("Editor"); } break;
        case W_View_Settings: { Result = StrLit("Settings"); } break;
        case W_View_TextEditor:
        {
            workspace_view_text_editor *Editor = (workspace_view_text_editor *)View->Data;
            if(AreEqual(Editor->FileName, StrLit("")))
            {
                Result = StrLit("Open File");
            }
            else
            {
                //if(Editor->History.At == &Editor->History.Sentinel)
                if(Editor->History.At == Editor->SavePoint)
                {
                    Result = PushString(W_FrameArena(), Editor->FileName);
                }
                else
                {
                    Result = PushFormat(W_FrameArena(), "* %S", Editor->FileName);
                }
            }
        } break;
        case W_View_SceneView: { Result = StrLit("Scene View"); } break;
        case W_View_CommandPalette: { Result = StrLit("Command Palette"); } break;
        case W_View_CharacterEditor: { Result = StrLit("Character Editor"); } break;
    }
    
    return(Result);
}

//- sixten: Builder code
static void W_ViewListerInputCallback(render_group *Group, glyph_atlas *Atlas, ui_box *Box, void *Data)
{
    workspace_view_command_palette *CommandPalette = (workspace_view_command_palette *)Data;
    string ToCursor = MakeString(Box->String.Data, CommandPalette->ListerInputEditState.Cursor);
    string ToMark = MakeString(Box->String.Data, CommandPalette->ListerInputEditState.Mark);
    
    r32 TargetCursorX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToCursor);
    r32 TargetMarkerX = CalculateRasterizedTextWidth(Atlas, Box->Font, Box->FontSize, ToMark);
    
    r32 CursorX = AC_AnimateValueF(TargetCursorX, 0, 0.175, "Workspace View Input Cursor %p", Box);
    r32 MarkerX = AC_AnimateValueF(TargetMarkerX, 0, 0.175, "Workspace View Input Mark %p", Box);
    
    v2 BoxDim = DimOfRange(Box->Rect);
    
    // sixten: Draw selection
    {
        v2 Offset = V2(7.5, (BoxDim.y - Box->FontSize) / 2);
        v2 Dim = V2(0, Box->FontSize);
        if(CursorX > MarkerX)
        {
            Offset.x += MarkerX;
            Dim.x = CursorX - MarkerX;
        }
        else
        {
            Offset.x += CursorX;
            Dim.x = MarkerX - CursorX;
        }
        
        v2 P = Box->Rect.Min + Offset;
        v4 Color = V4(0.4, 0.7, 0.8, 0.3);
        PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
    }
    
    // sixten: Draw cursor
    if(CommandPalette->ListerFieldSelected)
    {
        range1_r32 CursorSpan = Range1R32(CursorX, TargetCursorX);
        r32 Height = Box->FontSize + 4;
        v2 Offset = V2(7.5F + CursorSpan.Min, (BoxDim.y - Height) / 2);
        v2 Dim = V2(1.25F + CursorSpan.Max - CursorSpan.Min, Height);
        
        v2 P = Box->Rect.Min + Offset;
        v4 Color = V4(0.3, 1, 0.3, 0.7);
        PushQuad(Group, Range2R32(P, P+Dim), Color, 0, 0, 0);
    }
}

static void W_BuildViewTypeLister(workspace_view *View)
{
    workspace_view_command_palette *CommandPalette = (workspace_view_command_palette *)View->Data;
    
    workspace *Workspace = W_GetState();
    
    temporary_memory Scratch = GetScratch(0, 0);
    
    UI_Size(UI_Percent(1, 1), UI_Percent(1, 1))
        UI_Parent(UI_MakeBox(0, StrLit("")))
    {
        UI_Spacer(UI_Pixels(1.25, 1));
        UI_CornerRadius(4)
            UI_BackgroundColor(V4(0.5, 0.2, 0.3, 1.0))
            UI_LayoutAxis(Axis2_X)
            UI_Height(UI_Pixels(30, 1))
            UI_Parent(UI_MakeBoxF(UI_BoxFlag_DrawBackground|UI_BoxFlag_DrawDropShadow, "Workspace View Lister Header"))
        {
            UI_Spacer(UI_Pixels(5, 1));
            
            UI_Width(UI_TextContent(10, 1)) UI_LabelF("Open View:");
            
            UI_Spacer(UI_Pixels(15, 1));
            
            // sixten: Input Field.
            {
                r32 SelectedTransition = AC_AnimateValueF(CommandPalette->ListerFieldSelected ? 1.0 : 0.0,
                                                          0, 0.125, "View Input Field %p", View);
                
                v4 BorderColor = UI_TopBackgroundColor()*2;
                BorderColor.w = SelectedTransition;
                
                UI_SetNextBorderColor(BorderColor);
                
                UI_SetNextBackgroundColor(LinearBlend(V4(0, 0, 0, 1), UI_TopBackgroundColor(), 0.5));
                UI_SetNextWidth(UI_Percent(1, 0));
                
                ui_box *InputBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground |
                                               UI_BoxFlag_Clickable      |
                                               UI_BoxFlag_DrawBorder,
                                               "View Type Lister Input");
                
                UI_Parent(InputBox)
                {
                    UI_SetNextWidth(UI_TextContent(15, 1));
                    
                    ui_box *InputTextBox = UI_MakeBox(UI_BoxFlag_DrawText, StrLit("Workspace View Lister"));
                    InputTextBox->String = MakeString(CommandPalette->ListerInput, CommandPalette->ListerInputUsed);
                    UI_EquipBoxCustomDrawCallback(InputTextBox, W_ViewListerInputCallback, CommandPalette);
                }
                
                UI_Spacer(UI_Pixels(4, 1));
                
                if(CommandPalette->ListerFieldSelected)
                {
                    for(platform_event *Event = Workspace->EventList->First;
                        Event != 0;
                        Event = Event->Next)
                    {
                        if(Event->Type == PlatformEvent_Press || Event->Type == PlatformEvent_Text)
                        {
                            text_action Action = SingleLineTextActionFromEvent(Event);
                            if(IsValid(&Action))
                            {
                                text_op Op = TextOpFromAction(Scratch.Arena, MakeString(CommandPalette->ListerInput, CommandPalette->ListerInputUsed),
                                                              &CommandPalette->ListerInputEditState, &Action);
                                
                                string Left = MakeString(CommandPalette->ListerInput, Op.Range.Min);
                                string Right = MakeString(CommandPalette->ListerInput + Op.Range.Max, CommandPalette->ListerInputUsed - Op.Range.Max);
                                
                                u64 NewStringSize = Left.Count + Right.Count + Op.ReplaceString.Count;
                                char *NewString = PushArray(Scratch.Arena, char, NewStringSize);
                                Copy(NewString, Left.Data, Left.Count);
                                Copy(NewString + Left.Count, Op.ReplaceString.Data, Op.ReplaceString.Count);
                                Copy(NewString + Left.Count + Op.ReplaceString.Count, Right.Data, Right.Count);
                                
                                CommandPalette->ListerInputUsed = Minimum(ArrayCount(CommandPalette->ListerInput), NewStringSize);
                                Copy(CommandPalette->ListerInput, NewString, CommandPalette->ListerInputUsed);
                                
                                CommandPalette->ListerInputEditState.Cursor = Minimum(Op.NewCursor, CommandPalette->ListerInputUsed);
                                CommandPalette->ListerInputEditState.Mark = Minimum(Op.NewMark, CommandPalette->ListerInputUsed);
                            }
                        }
                    }
                }
                
                if(UI_SignalFromBox(InputBox).Pressed)
                {
                    CommandPalette->ListerFieldSelected = true;
                }
                
                ui *UI = UI_GetState();
                
                if(!(AreEqual(UI->Active, UI_EmptyKey()) || AreEqual(UI->Active, InputBox->Key)))
                {
                    CommandPalette->ListerFieldSelected = false;
                }
            }
        }
        
        UI_Spacer(UI_Pixels(15, 1));
        
        {
            UI_SetNextCornerRadius(10);
            UI_SetNextBackgroundColor(V4(0.15, 0.15, 0.15, 1.0));
            UI_SetNextBorderColor(V4(0.35, 0.35, 0.35, 1.0));
            UI_SetNextSize(UI_Percent(1, 1), UI_Pixels(100, 1));
            UI_SetNextLayoutAxis(Axis2_Y);
            
            ui_box *ButtonBox = UI_MakeBox(UI_BoxFlag_DrawBackground  |
                                           UI_BoxFlag_DrawBorder      |
                                           UI_BoxFlag_HotAnimation    |
                                           UI_BoxFlag_ActiveAnimation |
                                           UI_BoxFlag_Clickable,
                                           StrLit("Type Lister Box"));
            
            UI_SignalFromBox(ButtonBox);
        }
    }
    
    ReleaseScratch(Scratch);
}

static void W_BuildSettingsTabButton(workspace_view_settings *Settings, char *Name, workspace_settings_category Category)
{
    b32 IsSelected = (Settings->Category == Category);
    
    v4 Color = LinearBlend(Theme_TextColor, Theme_HighlightBorderColor, AC_AnimateValueF(IsSelected, IsSelected, 0.3, "Workspace Settings %s %p", Name, Settings));
    
    UI_SetNextFont(Font_Bold);
    UI_SetNextHeight(UI_TextContent(0, 1));
    UI_SetNextTextColor(Color);
    
    ui_box *Box = UI_MakeBoxF(UI_BoxFlag_DrawText |
                              UI_BoxFlag_Clickable,
                              Name);
    
    ui_signal Signal = UI_SignalFromBox(Box);
    if(Signal.Hovering)
    {
        Platform.SetCursor(PlatformCursor_Hand);
    }
    if(Signal.Pressed)
    {
        Settings->Category = Category;
    }
}

static b32 UI_DropdownSelection(char **Alternatives, s32 AlternativeCount, b32 *Open, s32 *Selected)
{
    b32 Result = false;
    
    UI_SetNextLayoutAxis(Axis2_X);
    UI_Parent(UI_MakeBoxF(0, ""))
    {
        UI_LabelF("Refresh Rate:");
        UI_Spacer(UI_Pixels(10, 1));
        
        b32 ActiveInDropdown = false;
        
        UI_SetNextWidth(UI_Pixels(200, 1));
        UI_SetNextCornerRadius(4);
        UI_SetNextLayoutAxis(Axis2_X);
        ui_box *DropdownBox = UI_MakeBoxF(UI_BoxFlag_DrawBackground  |
                                          UI_BoxFlag_DrawBorder      |
                                          UI_BoxFlag_HotAnimation    |
                                          UI_BoxFlag_ActiveAnimation |
                                          UI_BoxFlag_Clickable,
                                          "Dropdown");
        UI_Parent(DropdownBox)
        {
            UI_Width(UI_Percent(1, 0)) UI_LabelF(Alternatives[*Selected]);
            UI_BackgroundColor(Theme_BorderColor) UI_Width(UI_Pixels(1, 1)) UI_MakeBoxF(UI_BoxFlag_DrawBackground, "");
            UI_Width(UI_Pixels(25, 1)) UI_Font(Font_Icons) UI_LabelF("%U", FontIcon_DownDir);
        }
        
        ui_signal DropdownSignal = UI_SignalFromBox(DropdownBox);
        if(DropdownSignal.Pressed)
        {
            *Open = !(*Open);
        }
        
        if(AreEqual(UI_GetActive(), DropdownBox->Key))
        {
            ActiveInDropdown = true;
        }
        
        r32 OpenTransition = AC_AnimateValueF(*Open, 0, 0.175, "UI Dropdown %p%p", Alternatives, Open);
        
        if(OpenTransition > 0.1)
        {
            UI_Tooltip
            {
                UI_SetNextFixedP(V2(DropdownBox->Rect.Min.x, DropdownBox->Rect.Max.y));
                UI_SetNextCornerRadius(4);
                UI_SetNextWidth(UI_Pixels(200, 1));
                UI_SetNextHeight(UI_ChildrenSum(OpenTransition, 1));
                UI_Parent(UI_MakeBoxF(UI_BoxFlag_Clip           |
                                      UI_BoxFlag_DrawDropShadow |
                                      UI_BoxFlag_FloatingX      |
                                      UI_BoxFlag_FloatingY, "Dropdown Contents"))
                {
                    UI_PushWidth(UI_Percent(1, 1));
                    
                    for(s64 Index = 0;
                        Index < Round(AlternativeCount*OpenTransition);
                        ++Index)
                    {
                        ui_signal ButtonSignal = UI_ButtonF(Alternatives[Index]);
                        if(AreEqual(UI_GetActive(), ButtonSignal.Box->Key))
                        {
                            ActiveInDropdown = true;
                        }
                        
                        if(ButtonSignal.Pressed)
                        {
                            *Selected = Index;
                            Result = true;
                        }
                    }
                    
                    UI_PopWidth();
                }
            }
        }
        
        if(!ActiveInDropdown && !AreEqual(UI_GetActive(), UI_EmptyKey()))
        {
            *Open = false;
        }
    }
    
    return(Result);
}

static void W_BuildSceneView(workspace_view *View)
{
    workspace *Workspace = W_GetState();
    SV_BuildSceneView(Workspace->Input);
}

static void W_BuildSettings(workspace_view *View)
{
    workspace_view_settings *Settings = (workspace_view_settings *)View->Data;
    workspace *Workspace = W_GetState();
    
    UI_Height(UI_ChildrenSum(1, 1))
        UI_Column() UI_Padding(UI_Pixels(50, 0))
        UI_Row() UI_Padding(UI_Pixels(50, 0))
    {
        UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1))
            UI_Font(Font_Bold) UI_FontSize(36)
            UI_LabelF("Settings");
    }
    
    UI_LayoutAxis(Axis2_X)
        UI_Size(UI_Percent(1, 0), UI_Percent(1, 0))
        UI_Parent(UI_MakeBoxF(0, ""))
    {
        UI_Width(UI_Pixels(300, 1))
            UI_Parent(UI_MakeBoxF(0, "Navigation"))
        {
            UI_Row() UI_Padding(UI_Pixels(50, 1))
                UI_Width(UI_Percent(1, 0)) UI_Column() UI_Padding(UI_Percent(1, 0))
                UI_Height(UI_ChildrenSum(1, 1)) UI_LayoutAxis(Axis2_Y) UI_Parent(UI_MakeBoxF(0, ""))
            {
                W_BuildSettingsTabButton(Settings, "All", W_Settings_All);
                UI_Spacer(UI_Pixels(30, 1));
                W_BuildSettingsTabButton(Settings, "General", W_Settings_General);
                UI_Spacer(UI_Pixels(30, 1));
                W_BuildSettingsTabButton(Settings, "Theme", W_Settings_Theme);
                UI_Spacer(UI_Pixels(30, 1));
                W_BuildSettingsTabButton(Settings, "Developer", W_Settings_Developer);
                
                UI_Spacer(UI_Pixels(150, 1));
            }
        }
        
        UI_CornerRadius(5)
            UI_Width(UI_Pixels(1.25, 1))
            UI_BackgroundColor(Color_Grey)
            UI_MakeBoxF(UI_BoxFlag_DrawBackground, "Separator");
        
        UI_Padding(UI_Pixels(70, 0))
            UI_LayoutAxis(Axis2_Y)
            UI_Width(UI_Percent(1, 0))
            UI_Parent(UI_MakeBoxF(0, "Tab"))
            UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1))
        {
            UI_SetNextSize(UI_Percent(1, 0), UI_Percent(1, 0));
            UI_Scroll(0, &Settings->GlobalScroll, UI_BoxFlag_Clip)
            {
                workspace_settings_category Category = Settings->Category;
                if(!Category || (Category == W_Settings_General))
                {
                    UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("General");
                    
                    char *Alternatives[] = {"15 Hz", "30 Hz", "60 Hz", "120 Hz", "144 Hz", "Uncapped", "V-Sync"};
                    s64 AlternativeMapping[] = {15, 30, 60, 120, 144, -1, 0};
                    
                    s32 DropdownSelected;
                    FindIndexOfElement(DropdownSelected, AlternativeMapping, 0, Workspace->Input->RefreshRate);
                    
                    if(UI_DropdownSelection(Alternatives, ArrayCount(Alternatives),
                                            &Settings->GeneralDropdownOpen, &DropdownSelected))
                    {
                        Workspace->Input->RefreshRate = AlternativeMapping[DropdownSelected];
                        Settings->GeneralDropdownOpen = false;
                    }
                    
                    UI_Spacer(UI_Pixels(50, 1));
                }
                
                if(!Category || (Category == W_Settings_Theme))
                {
                    UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Theme");
                    
                    UI_SetNextSize(UI_Percent(1, 1), UI_Em(13, 1));
                    
                    UI_Scroll(0, &Settings->ThemeScroll)
                    {
                        UI_Size(UI_Percent(1, 1), UI_Em(2, 1))
                        {
                            for(s32 Index = 0;
                                Index < 2;
                                ++Index)
                            {
                                UI_ButtonF("Hello#%i", Index);
                                UI_ButtonF("Line#%i", Index);
                                UI_ButtonF("Paint#%i", Index);
                                UI_ButtonF("Color#%i", Index);
                                UI_ButtonF("Design#%i", Index);
                                UI_ButtonF("Address#%i", Index);
                                UI_ButtonF("Brightness#%i", Index);
                            }
                        }
                    }
                    
                    UI_Spacer(UI_Pixels(50, 1));
                }
                
                if(!Category || (Category == W_Settings_Developer))
                {
                    UI_Font(Font_Bold) UI_FontSize(36) UI_LabelF("Developer");
                    UI_Checkbox(&DEBUG_DebugSettings->RenderUIDebugRects, StrLit("Render UI Debug Rects"));
                    UI_Spacer(UI_Pixels(5, 1));
                    UI_Checkbox(&DEBUG_DebugSettings->RenderFPSCounter, StrLit("Render FPS Counter"));
                    UI_Spacer(UI_Pixels(5, 1));
                    UI_Checkbox(&DEBUG_DebugSettings->ListHotAndActive, StrLit("List Hot & Active"));
                    
                    UI_Spacer(UI_Pixels(50, 1));
                }
            }
        }
    }
    
    UI_Spacer(UI_Pixels(50, 1));
}

static void W_BuildView(workspace_view *View)
{
    r32 ViewHighlightTransition =
        AC_AnimateValueF(W_ViewIsCurrent(View), 0, 0.25, "Workspace View Highlight %p", View);
    UI_SetNextBorderColor(LinearBlend(Theme_BorderColor, Theme_HighlightBorderColor, ViewHighlightTransition));
    UI_PushBackgroundColor(Theme_BackgroundColor);
    UI_SetNextCornerRadius(3);
    
    ui_box *ViewBox = UI_MakeBoxF(UI_BoxFlag_Clickable      |
                                  UI_BoxFlag_DrawBackground |
                                  UI_BoxFlag_DrawBorder     |
                                  UI_BoxFlag_Clip,
                                  "Workspace View %p", View);
    
    UI_Parent(ViewBox)
        UI_Size(UI_Percent(1, 0), UI_Percent(1, 0))
    {
        switch(View->Type)
        {
            case W_View_Startup:
            {
                UI_Row() UI_Padding(UI_Pixels(50, 0))
                    UI_Width(UI_ChildrenSum(1, 1)) UI_Column() UI_Padding(UI_Pixels(50, 0))
                {
                    UI_Size(UI_TextContent(0, 1), UI_TextContent(10, 1))
                    {
                        UI_Font(Font_Bold) UI_FontSize(36)
                            UI_LabelF("Welcome to VN");
                        UI_TextColor(Theme_BorderColor) UI_LabelF("An impractical way to make a game");
                        
                        UI_Spacer(UI_Percent(1, 0));
                        
                        UI_Checkbox(&DEBUG_DebugSettings->ShowWelcomeMessage, StrLit("Show this message on startup"));
                    }
                }
            } break;
            
            case W_View_CommandPalette:
            {
                W_BuildViewTypeLister(View);
            } break;
            
            case W_View_Editor:
            {
                Workspace_BuildEditor(View);
            } break;
            
            case W_View_Settings:
            {
                W_BuildSettings(View);
            } break;
            
            case W_View_TextEditor:
            {
                W_BuildTextEditor(View);
            } break;
            
            case W_View_SceneView:
            {
                W_BuildSceneView(View);
            } break;
            
            case W_View_CharacterEditor:
            {
                W_BuildCharacterEditorView(View);
            } break;
        }
    }
    
    UI_PopBackgroundColor();
    
    UI_SignalFromBox(ViewBox);
}
