/* Essentials YOOtheme Pro 2.2.16 build 0813.1608; ZOOlanders https://www.zoolanders.com; Copyright (C) Joolanders, SL; http://www.gnu.org/licenses/gpl.html GNU/GPL */

import { Decoration } from '@codemirror/view';
import { StateEffect, StateField } from '@codemirror/state';
import { EditorView, keymap } from '@codemirror/view';

export const addHighlight = StateEffect.define({
    map: mapRange,
});

export const removeHighlight = StateEffect.define({
    map: mapRange,
});

function cutRange(ranges, r) {
    let leftover = [];
    ranges.between(r.from, r.to, (from, to, deco) => {
        if (from < r.from) leftover.push(deco.range(from, r.from));
        if (to > r.to) leftover.push(deco.range(r.to, to));
    });
    return ranges.update({
        filterFrom: r.from,
        filterTo: r.to,
        filter: () => false,
        add: leftover,
    });
}

function addRange(ranges, r) {
    ranges.between(r.from, r.to, (from, to) => {
        if (from < r.from) r = { from, to: r.to };
        if (to > r.to) r = { from: r.from, to };
    });
    return ranges.update({
        filterFrom: r.from,
        filterTo: r.to,
        filter: () => false,
        add: [highlight.range(r.from, r.to)],
    });
}

function mapRange(range, change) {
    let from = change.mapPos(range.from),
        to = change.mapPos(range.to);
    return from < to ? { from, to } : undefined;
}

const highlight = Decoration.mark({
    attributes: { style: `background-color: rgba(255, 50, 0, 0.3)` },
});

const highlightedRanges = StateField.define({
    create() {
        return Decoration.none;
    },
    update(ranges, tr) {
        ranges = ranges.map(tr.changes);
        for (let e of tr.effects) {
            if (e.is(addHighlight)) ranges = addRange(ranges, e.value);
            else if (e.is(removeHighlight)) ranges = cutRange(ranges, e.value);
        }
        return ranges;
    },
    provide: (field) => EditorView.decorations.from(field),
});

// function highlightSelection(view) {
//     view.dispatch({
//         effects: addHighlight.of({ from: 1, to: 30 }),
//         // effects: view.state.selection.ranges.filter((r) => !r.empty).map((r) => {
//         //     // console.log(r);
//         //     return addHighlight.of(r)
//         // }),
//     });
//     return true;
// }

// function unhighlightSelection(view) {
//     let highlighted = view.state.field(highlightedRanges);
//     let effects = [];
//     for (let sel of view.state.selection.ranges) {
//         highlighted.between(sel.from, sel.to, (rFrom, rTo) => {
//             let from = Math.max(sel.from, rFrom),
//                 to = Math.min(sel.to, rTo);
//             if (from < to) effects.push(removeHighlight.of({ from, to }));
//         });
//     }
//     view.dispatch({ effects });
//     return true;
// }

// const highlightKeymap = keymap.of([
//     { key: 'Mod-h', run: highlightSelection },
//     { key: 'Shift-Mod-h', run: unhighlightSelection },
// ]);

export default [highlightedRanges];
