import "./styles.css";
import "primevue/resources/themes/aura-light-green/theme.css";
import "primeicons/primeicons.css";
import "primeflex/primeflex.css";

import { createPinia, defineStore } from 'pinia'

import { createMemoryHistory, createRouter } from 'vue-router'

import { createApp } from "vue";
import PrimeVue from 'primevue/config';
import App from "./App.vue";
import { invoke } from "@tauri-apps/api/tauri";

import { v4 as uuidv4 } from 'uuid';

import ToastService from 'primevue/toastservice';


const pinia = createPinia()

export enum NetworkingMethod {
    PublicServer = "PublicServer",
    Manual = "Manual",
    Standalone = "Standalone",
}

export interface NetworkConfig {
    instance_id: string,

    virtual_ipv4: string
    network_name: string
    network_secret: string

    networking_method: NetworkingMethod,

    public_server_url: string,
    peer_urls: Array<string>,

    proxy_cidrs: Array<string>,

    enable_vpn_portal: boolean,
    vpn_portal_listne_port: number,
    vpn_portal_client_network_addr: string,
    vpn_portal_client_network_len: number,

    advanced_settings: boolean,

    listener_urls: Array<string>,
    rpc_port: number,
}

function default_network(): NetworkConfig {
    return {
        instance_id: uuidv4(),

        virtual_ipv4: "",
        network_name: "default",
        network_secret: "",

        networking_method: NetworkingMethod.PublicServer,

        public_server_url: "tcp://easytier.public.kkrainbow.top:11010",
        peer_urls: [],

        proxy_cidrs: [],

        enable_vpn_portal: false,
        vpn_portal_listne_port: 22022,
        vpn_portal_client_network_addr: "",
        vpn_portal_client_network_len: 24,

        advanced_settings: false,

        listener_urls: [
            "tcp://0.0.0.0:11010",
            "udp://0.0.0.0:11010",
            "wg://0.0.0.0:11011",
        ],
        rpc_port: 15888,
    }
}

export interface NetworkInstance {
    instance_id: string,

    running: boolean,
    error_msg: string,

    detail: any,
}

export const useNetworkStore = defineStore('network', {
    state: () => {
        const networkList = [default_network()];
        return {
            // for initially empty lists
            networkList: networkList as NetworkConfig[],
            // for data that is not yet loaded
            curNetwork: networkList[0],

            // uuid -> instance
            instances: {} as Record<string, NetworkInstance>,

            networkInfos: {} as Record<string, any>,
        }
    },

    getters: {
        lastNetwork(): NetworkConfig {
            return this.networkList[this.networkList.length - 1];
        },

        curNetworkId(): string {
            return this.curNetwork.instance_id;
        },

        networkInstances(): Array<NetworkInstance> {
            return Object.values(this.instances);
        },

        networkInstanceIds(): Array<string> {
            return Object.keys(this.instances);
        }
    },

    actions: {
        addNewNetwork() {
            this.networkList.push(default_network());
        },

        delCurNetwork() {
            const curNetworkIdx = this.networkList.indexOf(this.curNetwork);
            this.networkList.splice(curNetworkIdx, 1);
            const nextCurNetworkIdx = Math.min(curNetworkIdx, this.networkList.length - 1);
            this.curNetwork = this.networkList[nextCurNetworkIdx];
        },

        removeNetworkInstance(instanceId: string) {
            delete this.instances[instanceId];
        },

        addNetworkInstance(instanceId: string) {
            this.instances[instanceId] = {
                instance_id: instanceId,
                running: false,
                error_msg: "",
                detail: {},
            };
        },

        updateWithNetworkInfos(networkInfos: Record<string, any>) {
            this.networkInfos = networkInfos;
            for (const [instanceId, info] of Object.entries(networkInfos)) {
                if (this.instances[instanceId] === undefined) {
                    this.addNetworkInstance(instanceId);
                }
                this.instances[instanceId].running = info["running"];
                this.instances[instanceId].error_msg = info["error_msg"];
                this.instances[instanceId].detail = info;
            }
        },

        loadFromLocalStorage() {
            const networkList = JSON.parse(localStorage.getItem("networkList") || '[]');
            let result = [];
            for (const cfg of networkList) {
                result.push({
                    ...default_network(),
                    ...cfg,
                });
            }
            if (result.length === 0) {
                result.push(default_network());
            }
            this.networkList = result;
            this.curNetwork = this.networkList[0];
        },

        saveToLocalStroage() {
            localStorage.setItem("networkList", JSON.stringify(this.networkList));
        }
    }
})

export async function parseNetworkConfig(cfg: NetworkConfig): Promise<string> {
    const ret: string = await invoke("parse_network_config", { cfg: JSON.stringify(cfg) });
    return ret;
}

export async function runNetworkInstance(cfg: NetworkConfig) {
    const ret: string = await invoke("run_network_instance", { cfg: JSON.stringify(cfg) });
    return ret;
}

export async function retainNetworkInstance(instanceIds: Array<string>) {
    const ret: string = await invoke("retain_network_instance", { instanceIds: JSON.stringify(instanceIds) });
    return ret;
}

export async function collectNetworkInfos() {
    const ret: string = await invoke("collect_network_infos", {});
    return JSON.parse(ret);
}

import { createI18n } from 'vue-i18n'

const messages = {
    en: {
        "network": "Network",
        "networking_method": "Networking Method",
        "public_server": "Public Server",
        "manual": "Manual",
        "standalone": "Standalone",
        "virtual_ipv4": "Virtual IPv4",
        "network_name": "Network Name",
        "network_secret": "Network Secret",
        "public_server_url": "Public Server URL",
        "peer_urls": "Peer URLs",
        "proxy_cidrs": "Subnet Proxy CIDRs",
        "enable_vpn_portal": "Enable VPN Portal",
        "vpn_portal_listen_port": "VPN Portal Listen Port",
        "vpn_portal_client_network": "Client Sub Network",
        "advanced_settings": "Advanced Settings",
        "listener_urls": "Listener URLs",
        "rpc_port": "RPC Port",
        "config_network": "Config Network",
        "running": "Running",
        "error_msg": "Error Message",
        "detail": "Detail",
        "add_new_network": "Add New Network",
        "del_cur_network": "Delete Current Network",
        "select_network": "Select Network",
        "network_instances": "Network Instances",
        "instance_id": "Instance ID",
        "network_infos": "Network Infos",
        "parse_network_config": "Parse Network Config",
        "retain_network_instance": "Retain Network Instance",
        "collect_network_infos": "Collect Network Infos",
        "settings": "Settings",
        "exchange_language": "切换中文",
        "exit": "Exit",

        "chips_placeholder": "e.g: {0}, press Enter to add",
        "off_text": "Press to disable",
        "on_text": "Press to enable",

        "show_config": "Show Config",
        "close": "Close",

        "my_node_info": "My Node Info",
        "peer_count": "Connected",
        "upload": "Upload",
        "download": "Download",
        "show_vpn_portal_config": "Show VPN Portal Config",
        "show_event_log": "Show Event Log",
        "peer_info": "Peer Info",
        "route_cost": "Route Cost",
        "hostname": "Hostname",
        "latency": "Latency",
        "upload_bytes": "Upload",
        "download_bytes": "Download",
        "loss_rate": "Loss Rate",

        "run_network": "Run Network",
        "stop_network": "Stop Network",
    },
    cn: {
        "network": "网络",
        "networking_method": "网络方式",
        "public_server": "公共服务器",
        "manual": "手动",
        "standalone": "独立",
        "virtual_ipv4": "虚拟IPv4地址",
        "network_name": "网络名称",
        "network_secret": "网络密码",
        "public_server_url": "公共服务器地址",
        "peer_urls": "对等节点地址",
        "proxy_cidrs": "子网代理CIDR",
        "enable_vpn_portal": "启用VPN门户",
        "vpn_portal_listen_port": "监听端口",
        "vpn_portal_client_network": "客户端子网",
        "advanced_settings": "高级设置",
        "listener_urls": "监听地址",
        "rpc_port": "RPC端口",
        "config_network": "配置网络",
        "running": "运行中",
        "error_msg": "错误信息",
        "detail": "详情",
        "add_new_network": "添加新网络",
        "del_cur_network": "删除当前网络",
        "select_network": "选择网络",
        "network_instances": "网络实例",
        "instance_id": "实例ID",
        "network_infos": "网络信息",
        "parse_network_config": "解析网络配置",
        "retain_network_instance": "保留网络实例",
        "collect_network_infos": "收集网络信息",
        "settings": "设置",
        "exchange_language": "Switch to English",
        "exit": "退出",
        "chips_placeholder": "例如: {0}, 按回车添加",
        "off_text": "点击关闭",
        "on_text": "点击开启",
        "show_config": "显示配置",
        "close": "关闭",

        "my_node_info": "当前节点信息",
        "peer_count": "已连接",
        "upload": "上传",
        "download": "下载",
        "show_vpn_portal_config": "显示VPN门户配置",
        "show_event_log": "显示事件日志",
        "peer_info": "节点信息",
        "hostname": "主机名",
        "route_cost": "路由",
        "latency": "延迟",
        "upload_bytes": "上传",
        "download_bytes": "下载",
        "loss_rate": "丢包率",

        "run_network": "运行网络",
        "stop_network": "停止网络",
    }
}

function saveLocaleToLocalStorage(locale: string) {
    localStorage.setItem("locale", locale);
}

export function loadLocaleFromLocalStorage(): 'en' | 'cn' {
    const v = localStorage.getItem("locale")
    if (v === 'en' || v === 'cn') {
        return v;
    } else {
        return 'en';
    }
}

export const i18n = createI18n({
    legacy: false,
    locale: 'en', // set locale
    fallbackLocale: 'cn', // set fallback locale
    messages,
})

export function changeLocale(locale: 'en' | 'cn') {
    i18n.global.locale.value = locale;
    saveLocaleToLocalStorage(locale);
}

const app = createApp(App);
app.use(i18n, { useScope: 'global' })
app.use(pinia)
app.use(PrimeVue);
app.use(ToastService);
app.mount("#app");

export const router = createRouter({
    history: createMemoryHistory(),
    routes: [{ path: "/", component: App }]
});
