import type {Gallery_Control, Gallery_Descriptor_Field, Gallery_Resource, Json_Value} from "./gallery_types";

export function field_visible(expression: string | undefined, data: Record<string, Json_Value> | undefined): boolean {
    if (!expression) return true;
    const equality = expression.match(/^\$\{\$self\.([A-Za-z_][A-Za-z0-9_]*) == '([^']*)'}$/);
    return equality ? String(data?.[equality[1]]) === equality[2] : true;
}
export function build_controls(resources: Gallery_Resource[] = []): Gallery_Control[] {
    const controls: Gallery_Control[] = [];
    const visit = (fields: Gallery_Descriptor_Field[], data: Record<string, Json_Value>, target: string, group: string, path: string[] = [], labels: string[] = []) => {
        for (const field of fields ?? []) {
            const presentation = field.presentation ?? {};
            if (!field_visible(presentation.visible_on, data)) continue;
            const field_path = [...path, field.name];
            const field_labels = [...labels, presentation.label ?? field.name];
            const value = data?.[field.name];
            if (field.children?.length) {
                visit(field.children, value && typeof value === "object" && !Array.isArray(value) ? value as Record<string, Json_Value> : {}, target, group, field_path, field_labels);
            } else if (field.editable) {
                controls.push({id: field_path.join("."), target, path: field_path, label: field_labels.join(" / "), api: field_path.join("."), description: presentation.description ?? "", group, input: presentation.control === "automatic" ? "text" : presentation.control ?? "text", minimum: field.minimum, maximum: field.maximum, step: field.multiple_of, options: presentation.options ?? [], value});
            }
        }
    };
    for (const resource of resources) visit(resource.descriptor?.fields ?? [], resource.data ?? {}, resource.target, resource.view?.title ?? resource.title ?? resource.descriptor?.label ?? "控件属性");
    return controls;
}
export function nested_patch(path: string[], value: Json_Value): Record<string, Json_Value> {
    let result: Json_Value = value;
    for (const key of [...path].reverse()) result = {[key]: result};
    return result as Record<string, Json_Value>;
}
