import '../../../../assert/js/assert.js';
import '../../../../globals.js';
import memoize from '../../../../phet-core/js/memoize.js';
import mutate from '../../../../phet-core/js/mutate.js';
import { HorizontalLayoutAlignValues, LayoutAlign, MARGIN_LAYOUT_CONFIGURABLE_OPTION_KEYS, MarginLayoutConfigurable, scenery, VerticalLayoutAlignValues } from '../../imports.js';
import assertMutuallyExclusiveOptions from '../../../../phet-core/js/assertMutuallyExclusiveOptions.js';
const GRID_CONFIGURABLE_OPTION_KEYS = [
    'xAlign',
    'yAlign',
    'stretch',
    'xStretch',
    'yStretch',
    'grow',
    'xGrow',
    'yGrow'
].concat(MARGIN_LAYOUT_CONFIGURABLE_OPTION_KEYS);
// (scenery-internal)
const GridConfigurable = memoize((type) => {
    return class GridConfigurableMixin extends MarginLayoutConfigurable(type) {
        /**
         * (scenery-internal)
         */
        constructor(...args) {
            super(...args);
            // (scenery-internal)
            this._xAlign = null;
            this._yAlign = null;
            this._xStretch = null;
            this._yStretch = null;
            this._xGrow = null;
            this._yGrow = null;
        }
        /**
         * (scenery-internal)
         */
        mutateConfigurable(options) {
            super.mutateConfigurable(options);
            assertMutuallyExclusiveOptions(options, ['stretch'], ['xStretch', 'yStretch']);
            assertMutuallyExclusiveOptions(options, ['grow'], ['xGrow', 'yGrow']);
            mutate(this, GRID_CONFIGURABLE_OPTION_KEYS, options);
        }
        /**
         * Resets values to the "base" state.
         *
         * This is the fallback state for a constraint where every value is defined and valid. If a cell does not have a
         * specific "overridden" value, or a constraint doesn't have an "overridden" value, then it will take the value
         * defined here.
         *
         * These should be the default values for constraints.
         *
         * (scenery-internal)
         */
        setConfigToBaseDefault() {
            this._xAlign = LayoutAlign.CENTER;
            this._yAlign = LayoutAlign.CENTER;
            this._xStretch = false;
            this._yStretch = false;
            this._xGrow = 0;
            this._yGrow = 0;
            super.setConfigToBaseDefault();
        }
        /**
         * Resets values to the "don't override anything, only inherit from the constraint" state
         *
         * These should be the default values for cells (e.g. "take all the behavior from the constraint, nothing is
         * overridden").
         *
         * (scenery-internal)
         */
        setConfigToInherit(ignoreOptions) {
            if (!ignoreOptions || ignoreOptions.xAlign === undefined) {
                this._xAlign = null;
            }
            if (!ignoreOptions || ignoreOptions.yAlign === undefined) {
                this._yAlign = null;
            }
            if (!ignoreOptions || (ignoreOptions.stretch === undefined && ignoreOptions.xStretch === undefined)) {
                this._xStretch = null;
            }
            if (!ignoreOptions || (ignoreOptions.stretch === undefined && ignoreOptions.yStretch === undefined)) {
                this._yStretch = null;
            }
            if (!ignoreOptions || (ignoreOptions.grow === undefined && ignoreOptions.xGrow === undefined)) {
                this._xGrow = null;
            }
            if (!ignoreOptions || (ignoreOptions.grow === undefined && ignoreOptions.yGrow === undefined)) {
                this._yGrow = null;
            }
            super.setConfigToInherit(ignoreOptions);
        }
        /**
         * (scenery-internal)
         */
        get xAlign() {
            const result = this._xAlign === null ? null : this._xAlign.horizontal;
            assert && assert(result === null || typeof result === 'string');
            return result;
        }
        /**
         * (scenery-internal)
         */
        set xAlign(value) {
            assert && assert(value === null || HorizontalLayoutAlignValues.includes(value), `align ${value} not supported, the valid values are ${HorizontalLayoutAlignValues} or null`);
            // remapping align values to an independent set, so they aren't orientation-dependent
            const mappedValue = LayoutAlign.horizontalAlignToInternal(value);
            assert && assert(mappedValue === null || mappedValue instanceof LayoutAlign);
            if (this._xAlign !== mappedValue) {
                this._xAlign = mappedValue;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get yAlign() {
            const result = this._yAlign === null ? null : this._yAlign.vertical;
            assert && assert(result === null || typeof result === 'string');
            return result;
        }
        /**
         * (scenery-internal)
         */
        set yAlign(value) {
            assert && assert(value === null || VerticalLayoutAlignValues.includes(value), `align ${value} not supported, the valid values are ${VerticalLayoutAlignValues} or null`);
            // remapping align values to an independent set, so they aren't orientation-dependent
            const mappedValue = LayoutAlign.verticalAlignToInternal(value);
            assert && assert(mappedValue === null || mappedValue instanceof LayoutAlign);
            if (this._yAlign !== mappedValue) {
                this._yAlign = mappedValue;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get grow() {
            assert && assert(this._xGrow === this._yGrow);
            return this._xGrow;
        }
        /**
         * (scenery-internal)
         */
        set grow(value) {
            assert && assert(value === null || (typeof value === 'number' && isFinite(value) && value >= 0));
            if (this._xGrow !== value || this._yGrow !== value) {
                this._xGrow = value;
                this._yGrow = value;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get xGrow() {
            return this._xGrow;
        }
        /**
         * (scenery-internal)
         */
        set xGrow(value) {
            assert && assert(value === null || (typeof value === 'number' && isFinite(value) && value >= 0));
            if (this._xGrow !== value) {
                this._xGrow = value;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get yGrow() {
            return this._yGrow;
        }
        /**
         * (scenery-internal)
         */
        set yGrow(value) {
            assert && assert(value === null || (typeof value === 'number' && isFinite(value) && value >= 0));
            if (this._yGrow !== value) {
                this._yGrow = value;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get stretch() {
            assert && assert(this._xStretch === this._yStretch);
            return this._xStretch;
        }
        /**
         * (scenery-internal)
         */
        set stretch(value) {
            assert && assert(value === null || typeof value === 'boolean');
            if (this._xStretch !== value || this._yStretch !== value) {
                this._xStretch = value;
                this._yStretch = value;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get xStretch() {
            return this._xStretch;
        }
        /**
         * (scenery-internal)
         */
        set xStretch(value) {
            assert && assert(value === null || typeof value === 'boolean');
            if (this._xStretch !== value) {
                this._xStretch = value;
                this.changedEmitter.emit();
            }
        }
        /**
         * (scenery-internal)
         */
        get yStretch() {
            return this._yStretch;
        }
        /**
         * (scenery-internal)
         */
        set yStretch(value) {
            assert && assert(value === null || typeof value === 'boolean');
            if (this._yStretch !== value) {
                this._yStretch = value;
                this.changedEmitter.emit();
            }
        }
    };
});
scenery.register('GridConfigurable', GridConfigurable);
export default GridConfigurable;
export { GRID_CONFIGURABLE_OPTION_KEYS };
//# sourceMappingURL=GridConfigurable.js.map