/**
 * Zenith Signal - Atomic Reactive Value
 *
 * A signal is the most basic reactive primitive. It holds a single value
 * and notifies subscribers when the value changes.
 *
 * Features:
 * - Getter/setter model
 * - Automatic dependency tracking
 * - Fine-grained reactivity (no component re-rendering)
 *
 * @example
 * ```ts
 * const count = zenSignal(0)
 *
 * // Read value
 * console.log(count()) // 0
 *
 * // Write value
 * count(1)
 *
 * // Or use .value
 * count.value = 2
 * console.log(count.value) // 2
 * ```
 */
import { trackDependency, notifySubscribers } from './tracking';
/**
 * Create a reactive signal
 *
 * @param initialValue - The initial value of the signal
 * @returns A signal that can be read and written
 */
export function zenSignal(initialValue) {
    const state = {
        value: initialValue,
        subscribers: new Set()
    };
    // The signal function - acts as both getter and setter
    function signal(newValue) {
        if (arguments.length === 0) {
            // Getter - track dependency and return value
            trackDependency(state.subscribers);
            return state.value;
        }
        else {
            // Setter - update value and notify
            const oldValue = state.value;
            state.value = newValue;
            if (!Object.is(oldValue, newValue)) {
                notifySubscribers(state.subscribers);
            }
            return state.value;
        }
    }
    // Add .value accessor
    Object.defineProperty(signal, 'value', {
        get() {
            trackDependency(state.subscribers);
            return state.value;
        },
        set(newValue) {
            const oldValue = state.value;
            state.value = newValue;
            if (!Object.is(oldValue, newValue)) {
                notifySubscribers(state.subscribers);
            }
        },
        enumerable: true,
        configurable: false
    });
    signal.peek = function () {
        return state.value;
    };
    signal.subscribe = function (fn) {
        const subscriber = () => fn(state.value);
        state.subscribers.add(subscriber);
        // Return unsubscribe function
        return () => {
            state.subscribers.delete(subscriber);
        };
    };
    return signal;
}
