import { _get, _post, _delete, toggleLoader } from "../modules/common.js";

interface Profile {
    admin: boolean;
    libraries: string;
    fromUser: string;
    ombi: boolean;
}

class profile implements Profile {
    private _row: HTMLTableRowElement;
    private _name: HTMLElement;
    private _adminChip: HTMLSpanElement;
    private _libraries: HTMLTableDataCellElement;
    private _ombiButton: HTMLSpanElement;
    private _fromUser: HTMLTableDataCellElement;
    private _defaultRadio: HTMLInputElement;
    private _ombi: boolean;

    get name(): string { return this._name.textContent; }
    set name(v: string) { this._name.textContent = v; }

    get admin(): boolean { return this._adminChip.classList.contains("chip"); }
    set admin(state: boolean) {
        if (state) {
            this._adminChip.classList.add("chip", "~info", "ml-2");
            this._adminChip.textContent = "Admin";
        } else {
            this._adminChip.classList.remove("chip", "~info", "ml-2");
            this._adminChip.textContent = "";
        }
    }

    get libraries(): string { return this._libraries.textContent; }
    set libraries(v: string) { this._libraries.textContent = v; }

    get ombi(): boolean { return this._ombi; }
    set ombi(v: boolean) {
        if (!window.ombiEnabled) return;
        this._ombi = v;
        if (v) {
            this._ombiButton.textContent = window.lang.strings("delete");
            this._ombiButton.classList.add("~critical");
            this._ombiButton.classList.remove("~neutral");
        } else {
            this._ombiButton.textContent = window.lang.strings("add");
            this._ombiButton.classList.add("~neutral");
            this._ombiButton.classList.remove("~critical");
        }
    }

    get fromUser(): string { return this._fromUser.textContent; }
    set fromUser(v: string) { this._fromUser.textContent = v; }
    
    get default(): boolean { return this._defaultRadio.checked; }
    set default(v: boolean) { this._defaultRadio.checked = v; }

    constructor(name: string, p: Profile) {
        this._row = document.createElement("tr") as HTMLTableRowElement;
        let innerHTML = `
            <td><b class="profile-name"></b> <span class="profile-admin"></span></td>
            <td><input type="radio" name="profile-default"></td>
        `;
        if (window.ombiEnabled) innerHTML += `
            <td><span class="button @low profile-ombi"></span></td>
        `;
        innerHTML += `
            <td class="profile-from ellipsis"></td>
            <td class="profile-libraries"></td>
            <td><span class="button ~critical @low">${window.lang.strings("delete")}</span></td>
        `;
        this._row.innerHTML = innerHTML;
        this._name = this._row.querySelector("b.profile-name");
        this._adminChip = this._row.querySelector("span.profile-admin") as HTMLSpanElement;
        this._libraries = this._row.querySelector("td.profile-libraries") as HTMLTableDataCellElement;
        if (window.ombiEnabled)
            this._ombiButton = this._row.querySelector("span.profile-ombi") as HTMLSpanElement;
        this._fromUser = this._row.querySelector("td.profile-from") as HTMLTableDataCellElement;
        this._defaultRadio = this._row.querySelector("input[type=radio]") as HTMLInputElement;
        this._defaultRadio.onclick = () => document.dispatchEvent(new CustomEvent("profiles-default", { detail: this.name }));
        (this._row.querySelector("span.\\~critical") as HTMLSpanElement).onclick = this.delete;

        this.update(name, p);
    }
    
    update = (name: string, p: Profile) => {
        this.name = name;
        this.admin = p.admin;
        this.fromUser = p.fromUser;
        this.libraries = p.libraries;
        this.ombi = p.ombi;
    }

    setOmbiFunc = (ombiFunc: (ombi: boolean) => void) => { this._ombiButton.onclick = () => ombiFunc(this._ombi); }

    remove = () => { document.dispatchEvent(new CustomEvent("profiles-delete", { detail: this._name })); this._row.remove(); }

    delete = () => _delete("/profiles", { "name": this.name }, (req: XMLHttpRequest) => {
        if (req.readyState == 4) {
            if (req.status == 200 || req.status == 204) {
                this.remove();
            } else {
                window.notifications.customError("profileDelete", window.lang.var("notifications", "errorDeleteProfile", `"${this.name}"`));
            }
        }
    })

    asElement = (): HTMLTableRowElement => { return this._row; }
}

interface profileResp {
    default_profile: string;
    profiles: { [name: string]: Profile };
}

export class ProfileEditor {
    private _table = document.getElementById("table-profiles") as HTMLTableElement;
    private _createButton = document.getElementById("button-profile-create") as HTMLSpanElement;
    private _profiles: { [name: string]: profile } = {};
    private _default: string;
    private _ombiProfiles: ombiProfiles;

    private _createForm = document.getElementById("form-add-profile") as HTMLFormElement;
    private _profileName = document.getElementById("add-profile-name") as HTMLInputElement;
    private _userSelect = document.getElementById("add-profile-user") as HTMLSelectElement;
    private _storeHomescreen = document.getElementById("add-profile-homescreen") as HTMLInputElement;

    get empty(): boolean { return (Object.keys(this._table.children).length == 0) }
    set empty(state: boolean) {
        if (state) {
            this._table.innerHTML = `<tr><td class="empty">${window.lang.strings("inviteNoInvites")}</td></tr>`
        } else if (this._table.querySelector("td.empty")) {
            this._table.textContent = ``;
        }
    }

    get default(): string { return this._default; }
    set default(v: string) {
        this._default = v;
        if (v != "") { this._profiles[v].default = true; }
        for (let name in this._profiles) {
            if (name != v) { this._profiles[name].default = false; }
        }
    }

    load = () => _get("/profiles", null, (req: XMLHttpRequest) => {
        if (req.readyState == 4) {
            if (req.status == 200) {
                let resp = req.response as profileResp;
                if (Object.keys(resp.profiles).length == 0) {
                    this.empty = true;
                } else {
                    this.empty = false;
                    for (let name in resp.profiles) {
                        if (name in this._profiles) {
                            this._profiles[name].update(name, resp.profiles[name]);
                        } else {
                            this._profiles[name] = new profile(name, resp.profiles[name]);
                            if (window.ombiEnabled)
                                this._profiles[name].setOmbiFunc((ombi: boolean) => {
                                    if (ombi) {
                                        this._ombiProfiles.delete(name, (req: XMLHttpRequest) => {
                                            if (req.readyState == 4) {
                                                if (req.status != 204) {
                                                    window.notifications.customError("errorDeleteOmbi", window.lang.notif("errorUnknown"));
                                                    return;
                                                }
                                                this._profiles[name].ombi = false;
                                            }
                                        });
                                    } else {
                                        window.modals.profiles.close();
                                        this._ombiProfiles.load(name);
                                    }
                                });
                            this._table.appendChild(this._profiles[name].asElement());
                        }
                    }
                }
                this.default = resp.default_profile;
                window.modals.profiles.show();
            } else {
                window.notifications.customError("profileEditor", window.lang.notif("errorLoadProfiles"));
            }
        }
    })

    constructor() {
        (document.getElementById('setting-profiles') as HTMLSpanElement).onclick = this.load;
        document.addEventListener("profiles-default", (event: CustomEvent) => {
            const prevDefault = this.default;
            const newDefault = event.detail;
            _post("/profiles/default", { "name": newDefault }, (req: XMLHttpRequest) => {
                if (req.readyState == 4) {
                    if (req.status == 200 || req.status == 204) {
                        this.default = newDefault;
                    } else {
                        this.default = prevDefault;
                        window.notifications.customError("profileDefault", window.lang.notif("errorSetDefaultProfile"));
                    }
                }
            });
        });
        document.addEventListener("profiles-delete", (event: CustomEvent) => {
            delete this._profiles[event.detail];
            this.load();
        });

        if (window.ombiEnabled)
            this._ombiProfiles = new ombiProfiles();

        this._createButton.onclick = () => _get("/users", null, (req: XMLHttpRequest) => {
            if (req.readyState == 4) {
                if (req.status == 200 || req.status == 204) {
                    let innerHTML = ``;
                    for (let user of req.response["users"]) {
                        innerHTML += `<option value="${user['id']}">${user['name']}</option>`;
                    }
                    this._userSelect.innerHTML = innerHTML;
                    this._storeHomescreen.checked = true;
                    window.modals.profiles.close();
                    window.modals.addProfile.show();
                } else {
                    window.notifications.customError("loadUsers", window.lang.notif("errorLoadUsers"));
                }
            }
        });

        this._createForm.onsubmit = (event: SubmitEvent) => {
            event.preventDefault();
            const button = this._createForm.querySelector("span.submit") as HTMLSpanElement;
            toggleLoader(button);
            let send = {
                "homescreen": this._storeHomescreen.checked,
                "id": this._userSelect.value,
                "name": this._profileName.value
            }
            _post("/profiles", send, (req: XMLHttpRequest) => {
                if (req.readyState == 4) {
                    toggleLoader(button);
                    window.modals.addProfile.close();
                    if (req.status == 200 || req.status == 204) {
                        this.load();
                        window.notifications.customSuccess("createProfile", window.lang.var("notifications", "createProfile", `"${send['name']}"`));
                    } else {
                        window.notifications.customError("createProfile", window.lang.var("notifications", "errorCreateProfile", `"${send['name']}"`));
                    }
                    window.modals.profiles.show();
                }
            })
        };

    }
}

interface ombiUser {
    id: string;
    name: string;
}

export class ombiProfiles {
    private _form: HTMLFormElement;
    private _select: HTMLSelectElement;
    private _users: { [id: string]: string } = {};
    private _currentProfile: string;

    constructor() {
        this._form = document.getElementById("form-ombi-defaults") as HTMLFormElement;
        this._form.onsubmit = this.send;
        this._select = this._form.querySelector("select") as HTMLSelectElement;
    }
    send = () => {
        const button = this._form.querySelector("span.submit") as HTMLSpanElement;
        toggleLoader(button);
        let resp = {} as ombiUser;
        resp.id = this._select.value;
        resp.name = this._users[resp.id];
        _post("/profiles/ombi/" + this._currentProfile, resp, (req: XMLHttpRequest) => {
            if (req.readyState == 4) {
                toggleLoader(button);
                if (req.status == 200 || req.status == 204) {
                    window.notifications.customSuccess("ombiDefaults", window.lang.notif("setOmbiProfile"));
                } else {
                    window.notifications.customError("ombiDefaults", window.lang.notif("errorSetOmbiProfile"));
                }
                window.modals.ombiProfile.close();
            }
        });
    }

    delete = (profile: string, post?: (req: XMLHttpRequest) => void) => _delete("/profiles/ombi/" + profile, null, post);

    load = (profile: string) => {
        this._currentProfile = profile;
        _get("/ombi/users", null, (req: XMLHttpRequest) => {
            if (req.readyState == 4) {
                if (req.status == 200 && "users" in req.response) {
                    const users = req.response["users"] as ombiUser[]; 
                    let innerHTML = "";
                    for (let user of users) {
                        this._users[user.id] = user.name;
                        innerHTML += `<option value="${user.id}">${user.name}</option>`;
                    }
                    this._select.innerHTML = innerHTML;
                    window.modals.ombiProfile.show();
                } else {
                    window.notifications.customError("ombiLoadError", window.lang.notif("errorLoadOmbiUsers"))
                }
            }
        });
    }
}
