/**
 * Field rendering decision utility
 *
 * Determines whether a field should be rendered based on:
 * - Dependency conditions
 * - Visibility state
 * - Deleted state
 * - User role permissions
 */
import { check_dependency } from '../dependency/index.js';
/**
 * Check if a field should be rendered
 *
 * Evaluates multiple conditions to determine field visibility:
 * 1. Dependency conditions (field shows only when dependent field has specific value)
 * 2. Visibility state (hidden fields are filtered for responders)
 * 3. Deleted state (deleted fields are skipped)
 *
 * @param field - Field configuration
 * @param form_data - Current form data for dependency checking
 * @param field_metadata - Optional field metadata with visibility/deleted state
 * @param options - Check options to enable/disable specific checks
 * @returns true if field should be rendered, false to skip
 *
 * @example
 * ```ts
 * // Basic usage
 * if (should_render_field(field, form_data)) {
 *   renderField(field);
 * }
 *
 * // With metadata and role
 * if (should_render_field(field, form_data, metadata, { user_role: 'responder' })) {
 *   renderField(field);
 * }
 *
 * // Skip dependency checks (show all fields regardless of conditions)
 * if (should_render_field(field, form_data, metadata, { check_dependencies: false })) {
 *   renderField(field);
 * }
 * ```
 */
export function should_render_field(field, form_data, field_metadata, options = {}) {
    const { check_dependencies: should_check_dependency = true, check_visibility = true, check_deleted = true, user_role = 'author', } = options;
    // Check deleted state
    if (check_deleted && field_metadata?.deleted) {
        return false;
    }
    // Check visibility state (responders cannot see hidden fields; force_hide_hidden overrides)
    if (check_visibility) {
        const visibility = field_metadata?.visibility ?? field.visibility ?? 'visible';
        if (visibility === 'hidden') {
            if (user_role === 'responder')
                return false;
            if (options.force_hide_hidden)
                return false;
        }
    }
    // Check dependency condition
    if (should_check_dependency && field.dependency) {
        if (!check_dependency(field.dependency, form_data)) {
            return false;
        }
    }
    return true;
}
/**
 * Check if a field value is considered "empty"
 *
 * Empty values: undefined, null, empty string, empty array
 *
 * @param value - Field value to check
 * @returns true if value is empty
 */
export function is_field_empty(value) {
    if (value === undefined || value === null)
        return true;
    if (typeof value === 'string' && value.trim() === '')
        return true;
    if (Array.isArray(value) && value.length === 0)
        return true;
    return false;
}
/**
 * Get field value from form data
 *
 * Supports nested paths using dot notation (e.g., "group.field").
 *
 * @param field_id - Field ID or nested path
 * @param form_data - Form data record
 * @returns Field value or undefined
 */
export function get_field_value(field_id, form_data) {
    // Direct lookup first
    if (field_id in form_data) {
        return form_data[field_id];
    }
    // Handle nested path (e.g., "group.field")
    if (field_id.includes('.')) {
        const parts = field_id.split('.');
        let current = form_data;
        for (const part of parts) {
            if (current && typeof current === 'object' && part in current) {
                current = current[part];
            }
            else {
                return undefined;
            }
        }
        return current;
    }
    return undefined;
}
/**
 * Check if a group has any visible children (recursive).
 *
 * Groups with files are always considered to have visible content.
 *
 * @param group - Group field to check
 * @param form_data - Current form data (used for dependency and file checks)
 * @param field_metadata_map - Map of field_id → FieldMetadata
 * @param options - Render check options (same as should_render_field)
 * @returns true if at least one child would render
 */
export function has_visible_children(group, form_data, field_metadata_map, options = {}) {
    // Groups with files always have visible content
    const files = form_data[`__files_${group.id}`];
    const private_files = form_data[`__private_files_${group.id}`];
    if (Array.isArray(files) && files.length > 0)
        return true;
    if (Array.isArray(private_files) && private_files.length > 0)
        return true;
    if (!group.fields?.length)
        return false;
    return group.fields.some(child => {
        const child_metadata = field_metadata_map[child.id];
        if (!should_render_field(child, form_data, child_metadata, options))
            return false;
        // Recurse into nested groups
        if (child.field_type === 'group') {
            return has_visible_children(child, form_data, field_metadata_map, options);
        }
        return true;
    });
}
/**
 * Check if any group in a list has visible content.
 *
 * @param groups - Array of groups to check
 * @param form_data - Current form data
 * @param field_metadata_map - Map of field_id → FieldMetadata
 * @param options - Render check options
 * @returns true if at least one group has visible content
 */
export function has_visible_groups(groups, form_data, field_metadata_map, options = {}) {
    return groups.some(group => {
        const group_metadata = field_metadata_map[group.id];
        // If the group itself is filtered (deleted, hidden, dependency), skip it
        if (!should_render_field(group, form_data, group_metadata, options))
            return false;
        // Non-group fields at section level are always visible if they pass should_render_field
        if (group.field_type !== 'group')
            return true;
        return has_visible_children(group, form_data, field_metadata_map, options);
    });
}
//# sourceMappingURL=should_render_field.js.map