<div class="timeline-container">
    <div class="period" style="left: 0%; width: 20%">
        <div class="period-handle left"></div>
        <div class="period-handle right"></div>
        <div class="period-time">Time</div>
    </div>
</div>
<script>


    const timelineContainer = document.querySelector(".timeline-container");
    const periodTimeLine = document.querySelector(".period");
    const t_start = {{ t_start }};
    const t_end = {{ t_end }};

    const tick_time = 60 / {{ tick_time }};
    const tick_delay = 1 / tick_time;

    const period_default = {{ periode_defaut }};

    let handleMoving = false;

    function createTicks() {
        let i = t_start;

        while (i <= t_end) {
            const hourTick = document.createElement("div");
            hourTick.classList.add("tick", "hour");
            hourTick.style.left = `${((i - t_start) / (t_end - t_start)) * 100}%`;
            timelineContainer.appendChild(hourTick);

            const tickLabel = document.createElement("div");
            tickLabel.classList.add("tick-label");
            tickLabel.style.left = `${((i - t_start) / (t_end - t_start)) * 100}%`;
            tickLabel.textContent = numberToTime(i);
            timelineContainer.appendChild(tickLabel);

            if (i < t_end) {
                let j = Math.floor(i + 1);

                while (i < j) {
                    i += tick_delay;

                    if (i <= t_end) {
                        const quarterTick = document.createElement("div");
                        quarterTick.classList.add("tick", "quarter");
                        quarterTick.style.left = `${computePercentage(i, t_start)}%`;
                        timelineContainer.appendChild(quarterTick);
                    }

                }
                i = j;
            } else {
                i++;
            }
        }
    }

    function numberToTime(num) {
        const integer = Math.floor(num);
        const decimal = Math.round((num % 1) * 60);

        let dec = `:${decimal}`;
        if (decimal < 10) {
            dec = `:0${decimal}`;
        }

        let int = `${integer}`;
        if (integer < 10) {
            int = `0${integer}`;
        }

        return int + dec;

    }

    function snapToQuarter(value) {


        return Math.round(value * tick_time) / tick_time;
    }

    function updatePeriodTimeLabel() {
        const values = getPeriodValues();
        const deb = numberToTime(values[0])
        const fin = numberToTime(values[1])
        const text = `${deb} - ${fin}`
        periodTimeLine.querySelector('.period-time').textContent = text;

    }

    function timelineMainEvent(event) {

        const startX = (event.clientX || event.changedTouches[0].clientX);

        if (event.target.classList.contains("period-handle")) {
            const startWidth = parseFloat(periodTimeLine.style.width);
            const startLeft = parseFloat(periodTimeLine.style.left);
            const isLeftHandle = event.target.classList.contains("left");
            handleMoving = true
            const onMouseMove = (moveEvent) => {

                if (!handleMoving) return;

                const deltaX = (moveEvent.clientX || moveEvent.changedTouches[0].clientX) - startX;
                const containerWidth = timelineContainer.clientWidth;
                const newWidth =
                    startWidth + ((isLeftHandle ? -deltaX : deltaX) / containerWidth) * 100;

                if (isLeftHandle) {
                    const newLeft = startLeft + (deltaX / containerWidth) * 100;
                    adjustPeriodPosition(newLeft, newWidth);
                } else {
                    adjustPeriodPosition(parseFloat(periodTimeLine.style.left), newWidth);
                }

                updatePeriodTimeLabel();
            };
            const mouseUp = () => {
                snapHandlesToQuarters();
                timelineContainer.removeEventListener("mousemove", onMouseMove);
                handleMoving = false;
                func_call();

            }
            timelineContainer.addEventListener("mousemove", onMouseMove);
            timelineContainer.addEventListener("touchmove", onMouseMove);
            document.addEventListener(
                "mouseup",
                mouseUp,
                { once: true }
            );
            document.addEventListener(
                "touchend",
                mouseUp,
                { once: true }

            );
        } else if (event.target === periodTimeLine) {

            const startLeft = parseFloat(periodTimeLine.style.left);

            const onMouseMove = (moveEvent) => {
                if (handleMoving) return;
                const deltaX = (moveEvent.clientX || moveEvent.changedTouches[0].clientX) - startX;
                const containerWidth = timelineContainer.clientWidth;
                const newLeft = startLeft + (deltaX / containerWidth) * 100;

                adjustPeriodPosition(newLeft, parseFloat(periodTimeLine.style.width));

                updatePeriodTimeLabel();
            };
            const mouseUp = () => {
                snapHandlesToQuarters();
                timelineContainer.removeEventListener("mousemove", onMouseMove);
                func_call();
            }
            timelineContainer.addEventListener("mousemove", onMouseMove);
            timelineContainer.addEventListener("touchmove", onMouseMove);
            document.addEventListener(
                "mouseup",
                mouseUp,
                { once: true }
            );
            document.addEventListener(
                "touchend",
                mouseUp,
                { once: true }
            );
        }
    }

    let func_call = () => { };

    function setupTimeLine(callback) {
        func_call = callback;
        timelineContainer.addEventListener("mousedown", (e) => { timelineMainEvent(e) });
        timelineContainer.addEventListener("touchstart", (e) => { timelineMainEvent(e) });
    }

    function adjustPeriodPosition(newLeft, newWidth) {

        const snappedLeft = snapToQuarter(newLeft);
        const snappedWidth = snapToQuarter(newWidth);
        const minLeft = 0;
        const maxLeft = 100 - snappedWidth;

        const clampedLeft = Math.min(Math.max(snappedLeft, minLeft), maxLeft);

        periodTimeLine.style.left = `${clampedLeft}%`;
        periodTimeLine.style.width = `${snappedWidth}%`;
    }

    function getPeriodValues() {
        const leftPercentage = parseFloat(periodTimeLine.style.left);
        const widthPercentage = parseFloat(periodTimeLine.style.width);

        const startHour = (leftPercentage / 100) * (t_end - t_start) + t_start;
        const endHour = ((leftPercentage + widthPercentage) / 100) * (t_end - t_start) + t_start;

        const startValue = snapToQuarter(startHour);
        const endValue = snapToQuarter(endHour);

        const computedValues = [Math.max(startValue, t_start), Math.min(t_end, endValue)];

        if (computedValues[0] > t_end || computedValues[1] < t_start) {
            return [t_start, min(t_end, t_start + period_default)];
        }

        if (computedValues[1] - computedValues[0] <= tick_delay && computedValues[1] < t_end - tick_delay) {
            computedValues[1] += tick_delay;
        }

        return computedValues;
    }

    function setPeriodValues(deb, fin) {
        if (fin < deb) {
            throw new RangeError(`le paramètre 'deb' doit être inférieur au paramètre 'fin' ([${deb};${fin}])`)
        }

        if (deb < 0 || fin < 0) {
            throw new RangeError(`Les paramètres doivent être des entiers positifis ([${deb};${fin}])`)
        }

        deb = snapToQuarter(deb);
        fin = snapToQuarter(fin);
        let leftPercentage = (deb - t_start) / (t_end - t_start) * 100;
        let widthPercentage = (fin - deb) / (t_end - t_start) * 100;
        periodTimeLine.style.left = `${leftPercentage}%`;
        periodTimeLine.style.width = `${widthPercentage}%`;

        snapHandlesToQuarters();
        updatePeriodTimeLabel()
        func_call();
    }

    function snapHandlesToQuarters() {
        const periodValues = getPeriodValues();
        let lef = Math.min(computePercentage(Math.abs(periodValues[0]), t_start), computePercentage(Math.abs(t_end), tick_delay));
        if (lef < 0) {
            lef = 0;
        }
        const left = `${lef}%`;

        let wid = Math.max(computePercentage(Math.abs(periodValues[1]), Math.abs(periodValues[0])), computePercentage(tick_delay, 0));
        if (wid > 100) {
            wid = 100;
        }
        const width = `${wid}%`
        periodTimeLine.style.left = left;
        periodTimeLine.style.width = width;

        updatePeriodTimeLabel()
    }

    function computePercentage(a, b) {
        return ((a - b) / (t_end - t_start)) * 100;
    }
    function fromTime(time, separator = ":") {
        const [hours, minutes] = time.split(separator).map((el) => Number(el))
        return hours + minutes / 60
    }

    createTicks();

    setPeriodValues(t_start, t_start + period_default);

    {% if heures %}
    let [heure_deb, heure_fin] = [{{ heures | safe }}]
    if (heure_deb != '' && heure_fin != '') {
        heure_deb = fromTime(heure_deb);
        heure_fin = fromTime(heure_fin);
        setPeriodValues(heure_deb, heure_fin)
    }
    {% endif %}

</script>
<style>
    .timeline-container {
        width: 75%;
        margin-left: 25px;
        background-color: white;
        border-radius: 15px;
        position: relative;
        height: 40px;
        margin-bottom: 25px;
    }

    /* ... */
    .tick {
        position: absolute;
        bottom: 0;
        width: 1px;
        background-color: rgba(0, 0, 0, 0.5);
    }

    .tick.hour {
        height: 100%;
    }

    .tick.quarter {
        height: 50%;
    }

    .tick-label {
        position: absolute;
        bottom: 0;
        font-size: 12px;
        text-align: center;
        transform: translateY(100%) translateX(-50%);
        user-select: none;
        -webkit-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
    }


    .period {
        position: absolute;
        height: 100%;
        background-color: var(--color-secondary);
        border-radius: 15px;
    }

    .period-handle {
        position: absolute;
        top: 0;
        bottom: 0;
        width: 8px;
        border-radius: 0 4px 4px 0;
        cursor: col-resize;
    }

    .period-handle.right {
        right: 0;
        border-radius: 4px 0 0 4px;
    }

    .period .period-time {
        display: none;
        position: absolute;
        left: calc(50% - var(--w)/2 - 5px);
        justify-content: center;
        align-content: center;
        top: calc(-60% - 10px);
        --w: 10em;
        width: var(--w);
    }

    .period:hover .period-time {
        display: flex;

        background-color: var(--color-secondary);
        border-radius: 15px;
        padding: 5px;
    }
</style>