/* Copying and distribution of this file, with or without modification,
 * are permitted in any medium without royalty provided the copyright
 * notice and this notice are preserved.  This file is offered as-is,
 * without any warranty.
 */

static import std.array;
import std.conv : to;
static import std.file;
import std.format : format;
import std.stdio : stderr;
import std.process : environment;

import amalthea.dialog;
import amalthea.terminal : clearScreen;


void main() {
    auto menu = new Menu("Main menu", "", 18);

    auto yesno = new YesNo("YesNo", "Do you want to finish?");
    yesno.setButtonHandler(DialogAction.YES, { return; });
    yesno.setButtonHandler(DialogAction.NO,  { menu.run(); });

    menu.setButtonHandler(DialogAction.CANCEL, { yesno.run(); });
    menu.setButtonHandler(DialogAction.ESC,    { yesno.run(); });

    void fnInputBox() {
        auto inputBox = new InputBox("InputBox", "Enter your name:");
        inputBox.setButtonHandler(DialogAction.NO, { menu.run(); });
        inputBox.run();
        string name = inputBox.getEntry();
        auto infoBox = new InfoBox("", name ~ " is a very good programmer!");
        infoBox.setSleepTime(2); //the message will appear for two second
        infoBox.run();
        menu.run();
    }

    menu.addItem("1", "MsgBox");
    menu.addItem("2", "InputBox", &fnInputBox);
    menu.addItem("3", "RadioList");
    menu.addItem("4", "CheckList");
    menu.addItem("5", "Calendar");
    menu.addItem("6", "TimeBox");
    menu.addItem("7", "FSelect");
    menu.addItem("8", "DSelect");
    menu.addItem("9", "PasswordBox");
    menu.addItem("A", "BuildList");
    menu.addItem("B", "RangeBox");
    menu.addItem("C", "Pause");
    menu.addItem("D", "TextBox (open ~/.bashrc)");
    menu.addItem("E", "EditBox (open ~/.bashrc)");

    menu.setItemHandler("1", delegate() {
        auto msg = "Amalthea is a small library for D.\n"
            ~ "Dialog is a wrapper for the 'dialog' utility"
            ~ "\nfor the pseudographic user interface"
            ~ "\nand part of Amalthea.";
        auto msgbox = new MsgBox("Library", msg );
        msgbox.setButtonHandler(DialogAction.YES, { menu.run(); });
        msgbox.run();
    });

    void youChose(string info) {
        auto infoBox = new InfoBox("InputBox", "You chose: " ~ info);
        infoBox.setSleepTime(2); //the message will appear for two second
        infoBox.run();
        menu.run();
    }

    menu.setItemHandler("3", {
        auto radiolist = new RadioList("RadioList", "Your country:");
        string[] countries = ["Malta", "Mongolia", "Myanmar", "Other"];
        foreach(number, country; countries) {
            radiolist.addItem(to!string(number+1), country);
        }
        radiolist.run();
        string selectedItem = radiolist.getSelectedItem();
        if (selectedItem == "") selectedItem = "0";
        auto item = to!size_t(selectedItem) - 1;
        if (item >= 0) youChose(countries[item]);
    });

    menu.setItemHandler("4", {
        auto checklist = new CheckList("CheckList", "Programming languages");
        checklist.addItem("1", "D")
                 .addItem("2", "Fortran")
                 .addItem("3", "R")
                 .addItem("4", "OCaml");
        checklist.run();
        string items = std.array.join(checklist.getSelectedItems(), " ");
        youChose(items);
    });

    menu.setItemHandler("5", {
        auto calendar = new Calendar("Calendar", "Choose date...");
        calendar.setButtonHandler(DialogAction.NO, { menu.run(); });
        calendar.run();
        auto date = calendar.getDateTuple();
        youChose("Day: " ~ to!string(date.day) ~ "\n" ~
                 "Month: " ~ to!string(date.month) ~ "\n" ~
                 "Year: " ~ to!string(date.year) ~ "\n");
    });

    menu.setItemHandler("6", {
        auto timebox = new TimeBox("TimeBox", "Choose time...");
        timebox.setButtonHandler(DialogAction.NO, { menu.run(); });
        timebox.run();
        auto time = timebox.getTimeTuple();
        youChose(
            format("%02d", time.hour) ~ ":" ~
            format("%02d", time.minute) ~ ":" ~
            format("%02d", time.second)
        );
    });

    menu.setItemHandler("7", {
        auto fsviewer = new FSelect();
        fsviewer.run();
        youChose(fsviewer.getPath());
    });

    menu.setItemHandler("8", {
        auto fsviewer = new DSelect();
        fsviewer.run();
        youChose(fsviewer.getPath());
    });

    menu.setItemHandler("9", {
        auto passwordbox = new PasswordBox(
            "PasswordBox", "Enter unclassified data:"
        );
        passwordbox.setButtonHandler(DialogAction.NO, { menu.run(); });
        passwordbox.setButtonHandler(DialogAction.ESC, { menu.run(); });
        passwordbox.run();
        auto msg = passwordbox.getEntry();
        auto msgbox = new MsgBox("", "Your hidden input:\n" ~ msg);
        msgbox.setButtonHandler(DialogAction.YES, { menu.run(); });
        msgbox.run();
    });

    menu.setItemHandler("A", {
        auto buildlist = new BuildList(
            "BuildList", "Choose packages to install:"
        );
        auto packages = ["make", "gcc", "ldc", "dialog", "retext", "neovim"];
        foreach(number, pkg; packages) {
            buildlist.addItem(to!string(number+1), pkg);
        }
        buildlist.setButtonHandler(DialogAction.NO, { menu.run(); });
        buildlist.setButtonHandler(DialogAction.ESC, { menu.run(); });
        buildlist.run();
        auto selectedItems = buildlist.getSelectedItems();
        string text;
        foreach(item; selectedItems) {
            text ~= packages[item.to!int-1] ~ " ";
        }
        youChose(text);
    });

    menu.setItemHandler("B", {
        auto rangebox = new RangeBox("RangeBox", "Today's temperature (°C):");
        rangebox.setRange(-89, 58, 20);
        rangebox.setButtonHandler(DialogAction.NO, { menu.run(); });
        rangebox.setButtonHandler(DialogAction.ESC, { menu.run(); });
        rangebox.run();
        youChose(rangebox.getValue().to!string ~ "°C");
    });

    menu.setItemHandler("C", {
        auto text = "Warning!\nThis dialog will close when timeout expires.";
        auto pause = new Pause("Pause", text, 9, 54);
        pause.setTimeout(7);
        pause.setButtonHandler(DialogAction.OK, { menu.run(); });
        pause.setButtonHandler(DialogAction.NO, { menu.run(); });
        pause.setButtonHandler(DialogAction.ESC, { menu.run(); });
        pause.run();
    });

    menu.setItemHandler("D", {
        auto bashrc = environment["HOME"] ~ "/.bashrc";
        auto textbox = new TextBox("TextBox", bashrc, 20, 72);
        textbox.setButtonHandler(DialogAction.OK, { menu.run(); });
        textbox.setButtonHandler(DialogAction.ESC, { menu.run(); });
        textbox.run();
    });

    menu.setItemHandler("E", {
        // open and edit file
        auto bashrc = environment["HOME"] ~ "/.bashrc";
        auto editbox = new EditBox("EditBox", bashrc, 20, 72);
        editbox.setButtonHandler(DialogAction.NO, { menu.run(); });
        editbox.setButtonHandler(DialogAction.ESC, { menu.run(); });
        editbox.run();
        // save file
        auto inputbox = new InputBox("", "Enter path to save:");
        inputbox.setButtonHandler(DialogAction.OK, {
            std.file.write(inputbox.getEntry(), editbox.getContent());
        });
        inputbox.setButtonHandler(DialogAction.NO, { menu.run(); });
        inputbox.setButtonHandler(DialogAction.ESC, { menu.run(); });
        inputbox.run();
    });

    try {
        menu.run();
        clearScreen();
    } catch(Exception e) {
        stderr.writeln(e.msg);
    }
}
