import { ExportedMethod, PlugifyArrayType, PlugifyEnum, PlugifyType, Prototype } from "../types/plugify.js"

export enum EntityType {
    Unknown = 0,
    Function = 1,
    Enum = 2,
}

export const plugifyTypeConvert = (type: PlugifyType | PlugifyArrayType) => {
    switch (type) {
        case "string":
            return type;
        case "function":
            return plugifyCallbacksGenerator()
        case "void":
            return type; // void
        case "bool":
            return "boolean"
        case "char8":
        case "char16":
            return "string"
        case "int8":
        case "int16":
        case "int32":
        case "int64":
        case "uint8":
        case "uint16":
        case "uint32":
        case "uint64":
        case "ptr64":
        case "float":
        // todo: double is number or bigint?
        case "double":
            return "number";
        case "any":
            return type; // any
        case "vec2":
        case "vec3":
        case "vec4":
        case "mat4x4":
            return type;
        case "bool[]":
            return "boolean[]"
        case "char8[]":
        case "char16[]":
            return "string[]"
        case "int8[]":
        case "int16[]":
        case "int32[]":
        case "int64[]":
        case "uint8[]":
        case "uint16[]":
        case "uint32[]":
        case "uint64[]":
        case "ptr64[]":
        case "float[]":
        case "double[]":
            return "number[]"
        case "string[]":
            return type;
        case "any[]":
            return type;
        case "vec2[]":
        case "vec3[]":
        case "vec4[]":
        case "mat4x4[]":

        default:
            console.warn("Unknown type:", type)
            return type;
    }
}

export const plugifyNameConvert = (name: string) => {
    switch (name) {
        case "function":
            return "callback"
        default:
            return name;
    }
}

/**
 * 
 * @deprecated 
 */
export const plugifyCallbacksGenerator = () => {
    // todo: implement function maker
    return "(...args: unknown[]) => unknown"
}

export const plugifyParseEnums = (methods: ExportedMethod[]) => {
    const enumsMap = new Map<string, PlugifyEnum>();

    for (const method of methods) {
        for (const param of method.paramTypes) {
            // Parse Enums in method params
            if (param.enum && !enumsMap.has(param.enum.name) && param.enum.values) {
                enumsMap.set(param.enum.name, param.enum)
            }

            // Parse Enums in callback function(s) param(s)
            if (param.prototype && param.prototype.paramTypes) {
                for (const prototypeParam of param.prototype.paramTypes) {
                    if (prototypeParam.enum && !enumsMap.has(prototypeParam.enum.name) && prototypeParam.enum.values) {
                        enumsMap.set(prototypeParam.enum.name, prototypeParam.enum)
                    }
                }

                if (param.prototype.retType.enum && !enumsMap.has(param.prototype.retType.enum.name) && param.prototype.retType.enum.values) {
                    enumsMap.set(param.prototype.retType.enum.name, param.prototype.retType.enum)
                }
            }
        }

        if (method.retType.enum && !enumsMap.has(method.retType.enum.name) && method.retType.enum.values) {
            enumsMap.set(method.retType.enum.name, method.retType.enum)
        }
    }

    return enumsMap;
}

export const plugifyParseCallbacks = (methods: ExportedMethod[]) => {
    const map = new Map<string, Prototype>()

    for (const method of methods) {
        for (const param of method.paramTypes) {
            // Parse function/prototype types
            if (param.prototype && !map.has(param.prototype.name)) {
                map.set(param.prototype.name, param.prototype)
            }
        }
    }

    return map
}