
const typeface = {
    sans: "sans serif",
    serif: "Times New Roman"
};
const sizes = {
    small: "1rem",
    large: "3rem"
};
const colors = {
    red: "#ff2200",
    blue: "#0022ff"
};


const styles = new Map<string, string>();
function Mapper<T extends Record<string, string>>(className:string, propertyName:string, lut:T)
{
    const build =(_:T, propertyValue:string, customPropertyName?:string)=>
    {
        const selector = `${className}-${(customPropertyName||propertyValue as string).replace(/[^a-zA-Z0-9]/g, "")}${activeQuery?"_"+activeQuery:""}`;
        const check = styles.get(selector);
        if(!check)
        {
            const body = `{ ${propertyName}:${propertyValue}; }`;
            styles.set(selector, activeQuery ? `{ @media(${activeQuery})${body}}` : body);    
        }
        return selector;
    }
    type UseCustom = (custom:string)=>string;
    return new Proxy(function(override:string)
        {
            return build(lut, override);
        } as UseCustom,
        {
            get(target, prop){

                return build(lut, lut[prop as string], prop as string);
            }
        }
    ) as T & UseCustom;
}

export function Complex<Obj extends Record<string, string>, F extends CallableFunction>(obj:Obj, func:F)
{
    return new Proxy(func, {get(target, prop){
        return obj[prop as string]
    }}) as Obj & F
}

let activeQuery:false|string = false
function Query(amount:string)
{
    activeQuery = amount;
    return (...args:string[])=> {
        activeQuery = false;
        return args.join(" ");
    }
}

export function config<T>(obj:T)
{
    const CSS = {
        Sheet()
        {
            const rules = [];
            for(const [key, value] of styles.entries())
            {
                rules.push(key+value);
            }
            return rules.join("\n");
        },
        get MD()
        {
           return Query("768px");
        },
        Face: Mapper("Face", "font-family", {...typeface, ...obj}),
        Pad: Mapper("P", "padding", sizes)
    };
    return CSS;
}

export default config({});