
import { strictEquals } from '../equals.js';
import { BugIndicatingError } from '../errors.js';
import { subtransaction } from './base.js';
import { DebugNameData } from './debugName.js';
import { DerivedWithSetter } from './derived.js';

function observableReducerSettable(owner, options) {
    let prevValue = undefined;
    let hasValue = false;
    const d = ( new DerivedWithSetter(( new DebugNameData(owner, undefined, options.update)), (reader, changeSummary) => {
        if (!hasValue) {
            prevValue = options.initial instanceof Function ? options.initial() : options.initial;
            hasValue = true;
        }
        const newValue = options.update(reader, prevValue, changeSummary);
        prevValue = newValue;
        return newValue;
    }, options.changeTracker, () => {
        if (hasValue) {
            options.disposeFinal?.(prevValue);
            hasValue = false;
        }
    }, options.equalityComparer ?? strictEquals, (value, tx, change) => {
        if (!hasValue) {
            throw ( new BugIndicatingError('Can only set when there is a listener! This is to prevent leaks.'));
        }
        subtransaction(tx, tx => {
            prevValue = value;
            d.setValue(value, tx, change);
        });
    }));
    return d;
}

export { observableReducerSettable };
