Gui.App();

Window* sys_menu = Menu.New("System Menu");

U0 @system_menu_item_clicked(MenuItemWidget* widget)
{
    if (!widget->path)
        return;
    SystemStarter.CreateTask(widget->path, &widget->text);
}

U0 @system_menu_init()
{
    JsonObject* data = Json.ParseFile("M:/Settings/SystemMenu.json", erythros_mem_task);
    JsonArray* items = data->a("items");
    JsonArray* subitems = NULL;
    Window* submenu = NULL;
    I64 i;
    I64 j;
    // System Menu supports 2 levels of nesting to separate groups of Applications
    // into categories.
    for (i = 0; i < items->length; i++) {
        if (items->o(i)->@("name")) {
            if (items->o(i)->@("path")) {
                Menu.AddItem(
                    sys_menu, items->o(i)->@("name"),
                    @image_file_to_context2d(items->o(i)->@("icon")),
                    &@system_menu_item_clicked,
                    items->o(i)->@("path"));
            }
            if (items->o(i)->@("items")) {
                submenu = Menu.New(items->o(i)->@("name"));
                submenu->x = sys_menu->width;
                submenu->y = 35 + sys_menu->y + (MENU_ITEM_MIN_HEIGHT * i);
                subitems = items->o(i)->a("items");
                for (j = 0; j < subitems->length; j++) {
                    if (subitems->o(j)->@("name")) {
                        if (subitems->o(j)->@("path")) {
                            Menu.AddItem(submenu,
                                subitems->o(j)->@("name"),
                                @image_file_to_context2d(
                                    subitems->o(j)->@("icon")),
                                &@system_menu_item_clicked,
                                subitems->o(j)->@("path"));
                        }
                    }
                }
                Menu.AddItem(
                    sys_menu, items->o(i)->@("name"),
                    @image_file_to_context2d(items->o(i)->@("icon")),
                    NULL, NULL, submenu);
            }
        }
    }
}

U0 @system_menu_show(Context2DWidget* widget)
{
    sys_menu->x = 0;
    sys_menu->y = 32;
    if (widget->width == 30 && widget->height == 30) {
        widget->ctx->fill(Color(192, 192, 192));
    }
    Gui.Window.Show(sys_menu);
    Gui.Window.SetFocus(sys_menu);
    Gui.Window.Refresh(sys_menu);
}

U0 Main()
{
    Window* win = Compositor.CreateWindow(0, 0, Display.Width(), 32,
        WIN_FLAGS_NOHILIGHT | WIN_FLAGS_SKIP);
    Gui.Window.SetTitle(win, "AppBar");

    ButtonWidget* system_menu_btn = Gui.CreateWidget(win, WIDGET_TYPE_BUTTON, 0, 0, 58, 24);
    Gui.Widget.SetText(system_menu_btn, "");
    system_menu_btn->image = @image_file_to_context2d("system_menu.png");
    system_menu_btn->width = system_menu_btn->image->width + 8;

    Context2DWidget* separator = Gui.CreateWidget(
        win, WIDGET_TYPE_CONTEXT2D,
        system_menu_btn->x + system_menu_btn->width + 4, 2, 2, 20);
    separator->ctx = NewContext2D(2, 20);
    Line2D(separator->ctx, 0, 0, 0, 20, Color(224, 224, 224));
    Line2D(separator->ctx, 1, 0, 1, 20, Color(128, 128, 128));

    TextInputWidget* active_app_title = Gui.CreateWidget(
        win, WIDGET_TYPE_LABEL, separator->x + separator->width + 8, 8, 192, 64);

    if (!Compositor.active_win)
        Gui.Window.SetFocus(Compositor.GetWindowByTitle("Wallpaper"));

    Gui.Widget.SetFont(active_app_title, "Eight Bit Dragon");
    Gui.Widget.SetText(active_app_title, Compositor.active_win->title);

    CDateStruct ds;
    U8 clock_text[32];
    TextInputWidget* clock = Gui.CreateWidget(win, WIDGET_TYPE_LABEL, Display.Width() - 124, 8, 124, 32);
    Gui.Widget.SetFont(clock, "Eight Bit Dragon");
    Gui.Window.Refresh(win);

    // FIXME: This is an ugly way to do this...
    Compositor.menubar.win = win;
    Compositor.menubar.task = Fs;
    Compositor.menubar.title = active_app_title;

    Gui.Widget.SetCallback(system_menu_btn, "clicked", &@system_menu_show);

    // System Clock
    I64 min = -1;
    while (1) {
        Date2Struct(&ds, Now);
        if (ds.min != min) {
            StrPrint(&clock_text, "%3tZ %02d %03tZ, %02d:%02d", ds.day_of_week, "ST_DAYS_OF_WEEK", ds.day_of_mon, ds.mon - 1,
                "ST_MONTHS", ds.hour, ds.min);
            Gui.Widget.SetText(clock, &clock_text);
            Gui.Window.Refresh(win);
            min = ds.min;
        }
        if (Compositor.active_win != sys_menu && Gui.Window.IsVisible(sys_menu))
            Gui.Window.Hide(sys_menu);
        Sleep(1);
    }
}

@system_menu_init;
Main;