import { Fun, Optional } from '@ephox/katamari';
import { Keying } from '../../api/behaviour/Keying';
import { Receiving } from '../../api/behaviour/Receiving';
import { Representing } from '../../api/behaviour/Representing';
import * as SketchBehaviours from '../../api/component/SketchBehaviours';
import * as AlloyEvents from '../../api/events/AlloyEvents';
import * as NativeEvents from '../../api/events/NativeEvents';
import * as Channels from '../../api/messages/Channels';
import * as AlloyParts from '../../parts/AlloyParts';
import * as ModelCommon from './ModelCommon';
const sketch = (detail, components, _spec, _externals) => {
    const getThumb = (component) => AlloyParts.getPartOrDie(component, detail, 'thumb');
    const getSpectrum = (component) => AlloyParts.getPartOrDie(component, detail, 'spectrum');
    const getLeftEdge = (component) => AlloyParts.getPart(component, detail, 'left-edge');
    const getRightEdge = (component) => AlloyParts.getPart(component, detail, 'right-edge');
    const getTopEdge = (component) => AlloyParts.getPart(component, detail, 'top-edge');
    const getBottomEdge = (component) => AlloyParts.getPart(component, detail, 'bottom-edge');
    const modelDetail = detail.model;
    const model = modelDetail.manager;
    const refresh = (slider, thumb) => {
        model.setPositionFromValue(slider, thumb, detail, {
            getLeftEdge,
            getRightEdge,
            getTopEdge,
            getBottomEdge,
            getSpectrum
        });
    };
    const setValue = (slider, newValue) => {
        modelDetail.value.set(newValue);
        const thumb = getThumb(slider);
        refresh(slider, thumb);
    };
    const changeValue = (slider, newValue) => {
        setValue(slider, newValue);
        const thumb = getThumb(slider);
        detail.onChange(slider, thumb, newValue);
        return Optional.some(true);
    };
    const resetToMin = (slider) => {
        model.setToMin(slider, detail);
    };
    const resetToMax = (slider) => {
        model.setToMax(slider, detail);
    };
    const choose = (slider) => {
        const fireOnChoose = () => {
            AlloyParts.getPart(slider, detail, 'thumb').each((thumb) => {
                const value = modelDetail.value.get();
                detail.onChoose(slider, thumb, value);
            });
        };
        const wasDown = detail.mouseIsDown.get();
        detail.mouseIsDown.set(false);
        // We don't want this to fire if the mouse wasn't pressed down over anything other than the slider.
        if (wasDown) {
            fireOnChoose();
        }
    };
    const onDragStart = (slider, simulatedEvent) => {
        simulatedEvent.stop();
        detail.mouseIsDown.set(true);
        detail.onDragStart(slider, getThumb(slider));
    };
    const onDragEnd = (slider, simulatedEvent) => {
        simulatedEvent.stop();
        detail.onDragEnd(slider, getThumb(slider));
        choose(slider);
    };
    return {
        uid: detail.uid,
        dom: detail.dom,
        components,
        behaviours: SketchBehaviours.augment(detail.sliderBehaviours, [
            Keying.config({
                mode: 'special',
                focusIn: (slider) => {
                    return AlloyParts.getPart(slider, detail, 'spectrum').map(Keying.focusIn).map(Fun.always);
                }
            }),
            Representing.config({
                store: {
                    mode: 'manual',
                    getValue: (_) => {
                        return modelDetail.value.get();
                    },
                    setValue
                }
            }),
            Receiving.config({
                channels: {
                    [Channels.mouseReleased()]: {
                        onReceive: choose
                    }
                }
            })
        ]),
        events: AlloyEvents.derive([
            AlloyEvents.run(ModelCommon.sliderChangeEvent(), (slider, simulatedEvent) => {
                changeValue(slider, simulatedEvent.event.value);
            }),
            AlloyEvents.runOnAttached((slider, _simulatedEvent) => {
                // Set the initial value
                const getInitial = modelDetail.getInitialValue();
                modelDetail.value.set(getInitial);
                const thumb = getThumb(slider);
                refresh(slider, thumb);
                const spectrum = getSpectrum(slider);
                // Call onInit instead of onChange for the first value.
                detail.onInit(slider, thumb, spectrum, modelDetail.value.get());
            }),
            AlloyEvents.run(NativeEvents.touchstart(), onDragStart),
            AlloyEvents.run(NativeEvents.touchend(), onDragEnd),
            AlloyEvents.run(NativeEvents.mousedown(), onDragStart),
            AlloyEvents.run(NativeEvents.mouseup(), onDragEnd)
        ]),
        apis: {
            resetToMin,
            resetToMax,
            setValue,
            refresh
        },
        domModification: {
            styles: {
                position: 'relative'
            }
        }
    };
};
export { sketch };
//# sourceMappingURL=SliderUi.js.map