/**
 * Property Manager - Unified property lifecycle for web components
 *
 * Handles property/attribute synchronization, validation, coercion, and change tracking.
 * All property updates flow through a single code path for consistency.
 */
/**
 * Manages component properties with unified lifecycle
 */
export class PropertyManager {
    constructor(config) {
        this._props = new Map();
        this._config = config;
        this._initializeDefaults();
    }
    /**
     * Initialize properties with default values
     */
    _initializeDefaults() {
        for (const [name, config] of Object.entries(this._config)) {
            if (config.default !== undefined) {
                this._props.set(name, config.default);
            }
        }
    }
    /**
     * Update a property value
     * Returns PropertyChange if value changed, null otherwise
     */
    updateProperty(name, value, source = 'property') {
        const config = this._config[name];
        if (!config) {
            console.warn(`[PropertyManager] Unknown property: ${name}`);
            return null;
        }
        // Get old value
        const oldValue = this._props.get(name);
        // Coerce value to correct type
        const coercedValue = this._coerceValue(name, value, config);
        // Validate value
        if (!this._validateValue(name, coercedValue, config)) {
            console.warn(`[PropertyManager] Invalid value for ${name}:`, coercedValue);
            return null;
        }
        // Check if value actually changed
        if (this._valuesEqual(oldValue, coercedValue)) {
            return null;
        }
        // Update internal map
        this._props.set(name, coercedValue);
        // Create change object
        const change = {
            name,
            oldValue,
            newValue: coercedValue,
            source
        };
        return change;
    }
    /**
     * Coerce value to the correct type
     */
    _coerceValue(name, value, config) {
        // Custom coercion
        if (config.coerce) {
            return config.coerce(value);
        }
        // Null/undefined handling
        if (value === null || value === undefined) {
            return config.default ?? null;
        }
        // Type coercion
        switch (config.type) {
            case 'boolean':
                // Attribute presence = true, absence = false
                // Property: truthy/falsy coercion
                if (typeof value === 'string') {
                    return value !== 'false' && value !== '';
                }
                return Boolean(value);
            case 'number':
                const num = Number(value);
                return isNaN(num) ? (config.default ?? 0) : num;
            case 'string':
                return String(value);
            case 'object':
            case 'array':
                if (typeof value === 'string') {
                    try {
                        return JSON.parse(value);
                    }
                    catch {
                        console.warn(`[PropertyManager] Failed to parse ${name}:`, value);
                        return config.default ?? (config.type === 'array' ? [] : {});
                    }
                }
                return value;
            default:
                return value;
        }
    }
    /**
     * Validate a property value
     */
    _validateValue(name, value, config) {
        if (config.validate) {
            return config.validate(value);
        }
        return true;
    }
    /**
     * Check if two values are equal
     */
    _valuesEqual(a, b) {
        // Simple equality for primitives
        if (typeof a !== 'object' || typeof b !== 'object') {
            return a === b;
        }
        // Null checks
        if (a === null || b === null) {
            return a === b;
        }
        // Deep equality for objects/arrays (simple implementation)
        // For production, consider using a proper deep equality library
        try {
            return JSON.stringify(a) === JSON.stringify(b);
        }
        catch {
            return false;
        }
    }
    /**
     * Get a property value
     */
    get(name) {
        return this._props.get(name);
    }
    /**
     * Get all properties as an object
     */
    getAll() {
        return Object.fromEntries(this._props);
    }
    /**
     * Get property configuration
     */
    getConfig(name) {
        return this._config[name];
    }
    /**
     * Check if a property is visual (requires render)
     */
    isVisual(name) {
        return this._config[name]?.visual ?? false;
    }
    /**
     * Check if a property affects form value
     */
    isFormValue(name) {
        return this._config[name]?.formValue ?? false;
    }
    /**
     * Check if a property should emit change events
     */
    shouldEmitChange(name) {
        return this._config[name]?.emitChange ?? false;
    }
    /**
     * Handle property aliases (e.g., not-searchable → searchable: false)
     */
    handleAlias(aliasName, value) {
        // Find property with this alias
        for (const [propName, config] of Object.entries(this._config)) {
            if (config.aliases && aliasName in config.aliases) {
                const aliasedValue = config.aliases[aliasName];
                return this.updateProperty(propName, aliasedValue, 'attribute');
            }
        }
        return null;
    }
}
//# sourceMappingURL=property-manager.js.map