import { Palette, Button, VerticalBox, HorizontalBox, ScrollView, ListView, StandardListView } from "std-widgets.slint";

export struct ChangeData {
    hash: string,
    // TODO display all authors
    // authors: [string],
    author: string,
    timestamp: string,
    message: string,
}

export struct ChannelsData {
    names: [string],
    active: int,
}

component DeltasList {
    in property <string> delta;

    VerticalBox {
        Text {
            vertical-stretch: 0;
            text: "change";
        }

        ScrollView {
            vertical-stretch: 1;
            viewport-width <=> text.width;
            viewport-height <=> text.height;
            text := Text {
                width: 100%;
                text: delta;
            }
        }
    }
}

component DiffEntry inherits Rectangle {
    in property <int> files-count;

    VerticalBox {
        label := Text {
            text: "\{files-count} files changed";
        }
    }

    in-out property <bool> is-selected: false;
    in property <bool> has-hover;
    states [
        selected when root.is-selected: {
            root.background: Palette.selection-background;
            label.color: Palette.selection-foreground;
        }
        lowlighted when root.has-hover: {
            root.background: Palette.alternate-background;
            label.color: Palette.alternate-foreground;
        }
    ]
}

component ChangeEntry inherits Rectangle {
    in-out property <string> hash;
    in-out property <string> author;
    in-out property <string> timestamp;
    in-out property <string> message;

    // Each text element is given default text, in case it's empty
    // 1) it looks nicer
    // 2) it makes empty entries the same height as filled entries
    //    -> uniform-height entries are more performant in a ListView
    VerticalBox {
        spacing: 5px;

        msg-text := Text {
            text: message == "" ? "(no message)" : "\{root.message}";
            overflow: elide;
            font-italic: message == "";
        }

        author-text := Text {
            text: author == "" ? "(no author)" : "\{root.author}";
            overflow: elide;
            font-italic: true;
        }
    }

    in-out property <bool> is-selected: false;
    in property <bool> has-hover;
    states [
        selected when root.is-selected: {
            root.background: Palette.selection-background;
            msg-text.color: Palette.selection-foreground;
            author-text.color: Palette.selection-foreground;
        }
        lowlighted when root.has-hover: {
            root.background: Palette.alternate-background;
            msg-text.color: Palette.alternate-foreground;
            author-text.color: Palette.alternate-foreground;
        }
    ]
}

component Changelog inherits Rectangle {
    in-out property <int> count-files-changed;
    in-out property <[ChangeData]> changes_log: [];
    in-out property <int> selected: -2;
    public function deselect() {
        root.selected = -1;
    }
    callback selection-changed(/*new selection*/ int);

    VerticalBox {
        Text {
            vertical-stretch: 0;
            text: "log";
        }

        diff-entry := DiffEntry {
            files-count: count-files-changed;

            is-selected: root.selected == -1;
            has-hover: touch0.has-hover;

            touch0 := TouchArea {
                clicked => {
                    root.selected = -1;
                    root.selection-changed(-1);
                }
            }
        }

        // TODO convert to a StandardListView?
        ListView {
            // preferred-width: 400px;
            for change[index] in root.changes_log: ce := ChangeEntry {
                hash: change.hash;
                author: change.author;
                timestamp: change.timestamp;
                message: change.message;

                is-selected: root.selected == index;
                has-hover: touch.has-hover;

                touch := TouchArea {
                    clicked => {
                        root.selected = index;
                        root.selection-changed(index);
                    }
                }
            }
        }
    }
}

component ChannelsList {
    in-out property <[string]> channels;
    in-out property <int> active;

    VerticalBox {
        alignment: start;
        spacing: 0;
        preferred-width: 150px;

        Text {
            text: "channels";

        for ch in channels: Text {
            text: "\{ch}";
        }
        }
    }
}

component ChannelEntry inherits Rectangle {
    in property <string> name;
    in property <bool> active;

    HorizontalBox {
        alignment: start;
        spacing: 5px;
        padding: 0;

        active-marker := Rectangle {
            width: 10px;
            height: 100%;
            border-radius: 5px;
            visible: root.active;
            background: Palette.accent-background;
        }

        label-backdrop := Rectangle {
            label := Text {
                text: "\{name}";
            }
        }
    }

    in property <bool> is-selected: false;
    in property <bool> has-hover: false;

    states [
        selected when is-selected: {
            label-backdrop.background: Palette.selection-background;
            label.color: Palette.selection-foreground;
        }
        lowlighted when has-hover: {
            label-backdrop.background: Palette.alternate-background;
            label.color: Palette.alternate-foreground;
        }
        off when true: {
            label-backdrop.background: Palette.background;
            label.color: Palette.foreground;
        }
    ]
}

component ChannelsList {
    in-out property <ChannelsData> data;
    in-out property <int> selected: -1;
    public function deselect() {
        root.selected = -1;
    }
    callback selection-changed(/*new selection*/ int);

    VerticalBox {
        Text {
            vertical-stretch: 0;
            text: "channels";
        }

        // TODO convert to a StandardListView?
        ListView {
            for ch[index] in data.names: ChannelEntry {
                name: ch;
                active: data.active == index;

                is-selected: selected == index;
                has-hover: touch.has-hover;

                touch := TouchArea {
                    clicked => {
                        root.selected = index;
                        root.selection-changed(index);
                    }
                }
            }
        }
    }
}

export component AppWindow inherits Window {
    in-out property <[string]> channels <=> chs.channels;
    in-out property <int> active-channel <=> chs.active;
    preferred-width: 960px;
    preferred-height: 720px;

    in property <string> exe_path;
    in property <string> repo_path;
    in-out property <ChannelsData> channels <=> chs.data;
    in-out property <[ChangeData]> changes_log <=> log.changes_log;
    in-out property <int> count-files-changed <=> log.count-files-changed;
    in-out property <string> delta <=> deltas.delta;
    callback request-channel-list();
    callback request-change-delta(string);
    callback request-diff-summary(string);
    callback request-diff-delta(string);

    function fill-chs() {
        chs.deselect();
        root.request-channel-list();
    }

    function fill-log() {
        log.deselect();
        root.request-changes-log(chs.data.names[chs.selected]);
        root.request-diff-summary(chs.data.names[chs.selected]);
    }

    function fill-diff-view() {
        if log.selected >= 0 && log.selected < log.changes_log.length {
        } else {
        }
    }
    VerticalBox {
        Button {
            vertical-stretch: 0;
            text: "Refresh";
            clicked => {
                fill-chs();
                fill-log();
                fill-diff-view();
            }
        }

        HorizontalBox {
            vertical-stretch: 1;
            chs := ChannelsList {
                channels: [];
                active: 0;
                preferred-width: 500px;
            chs := ChannelsList {
                horizontal-stretch: 0;
                selection-changed => {
                    fill-log();
                    fill-diff-view();
                }
            }

            log := Changelog {
                horizontal-stretch: 2;
                selection-changed => {
                    fill-diff-view();
                }
            }

            deltas := DeltasList {
                horizontal-stretch: 3;
            }
        }
    }
}