import {MRPCConnector, type Session, type Response} from './api';
import {get, type Writable, writable} from 'svelte/store';
import {filesize} from 'filesize';

export * as api from './api';

export enum StateE { LOGIN, SIGNUP, RESET_PASSWORD, PROFILE, TFA_SETUP, ADMIN, VIEW }
export interface State {
    s: StateE,
    view_node: number
}
export interface UploadFile {
    id: number,
    name: string,
    full_name: string,
    file: File,
    overwrite: boolean
}

export const show_working = writable<boolean>(false);
export const info_banner = writable<string>('');
export const error_banner = writable<string>('');

export const state = writable<State>({s: StateE.LOGIN, view_node: 0});

export const rpc = new MRPCConnector('/mrpc');

export const token = writable<string|null>(localStorage.getItem('token'));
export const session: { s: Writable<Session|null>, update: (token: string|null) => Promise<void> } = {
    s: writable(null),
    update: async (t: string|null) => {
        console.log('S');
        if (t == null) {
            session.s.set(null);
            return;
        }
        const s = await rpc.Auth_session_info(t)
        if (s.e)
            token.set(null);
        else
            session.s.set(s.o);
    }
};
token.subscribe((t) => session.update(t));

token.subscribe(v => {
    if (v == null)
        localStorage.removeItem('token');
    else
        localStorage.setItem('token', v);
})


export function changeStateFunction(target: StateE, node?: number): () => void {
    return () => {
        const new_node = node ?? get(state).view_node;
        state.set({s: target, view_node: new_node});
    }
}

export async function workingWrapper<T>(fn: () => Promise<T>): Promise<T|null> {
    let r = null;
    error_banner.set('');
    show_working.set(true);
    try {
        r = await fn();
    } catch (e) {
        error_banner.set(`Error while making request: ${e}`);
    }
    show_working.set(false);
    return r;
}

export async function workingWrapperO(fn: () => Promise<string|null>): Promise<boolean> {
    const resp = await workingWrapper(fn);
    if (resp)
        error_banner.set(resp);
    if (resp === 'Unauthorized')
        token.set(null);
    return resp == null;
}

export async function workingWrapperR<T>(fn: () => Promise<Response<T>>): Promise<T|null> {
    const resp = await workingWrapper(fn);
    if (!resp)
        return null;
    if (resp.e === 'Unauthorized')
        token.set(null);
    else if (resp.e != null)
        error_banner.set(resp.e);
    return resp.o;
}

export async function download<T extends {id:number, file:boolean}>(token: string, nodes: T[]) {
    const form = document.createElement('form');
    form.method = 'POST';
    form.target = '_blank';
    form.innerHTML = `<input type="hidden" name="token" value="${token}">`;
    if (nodes.length == 1 && nodes[0].file) {
        form.action = '/download';
        form.innerHTML += `<input type="hidden" name="node" value="${nodes[0].id}}">`;
    } else {
        form.action = '/download_multi';
        form.innerHTML += `<input type="hidden" name="nodes" value="${nodes.map(n => n.id).join('.')}">`;
        const resp = await workingWrapperR<number>(() => rpc.FS_get_nodes_size(token, nodes.map(v => v.id)));
        if (!resp)
            return;
        info_banner.set(`Estimated size: ${filesize(resp, {base: 2, standard: 'jedec'})}`);
    }
    document.body.appendChild(form);
    form.submit();
    document.body.removeChild(form);
}
