import { adjustRangesForEdit } from './rich-text.js';

export function normalizedSelection(selection) {
  if (!selection || selection.start === selection.end) return null;
  return {
    start: Math.min(selection.start, selection.end),
    end: Math.max(selection.start, selection.end),
  };
}

export function deleteTextSelection(segment, cursor, selection) {
  const range = normalizedSelection(selection);
  if (!range) return { cursor, selection };
  const text = segment.text || '';
  segment.text = text.slice(0, range.start) + text.slice(range.end);
  segment.kerning?.splice(range.start, range.end - range.start);
  adjustRangesForEdit(segment, range.start, 0, range.end - range.start);
  return { cursor: range.start, selection: null };
}

export function insertText(segment, cursor, selection, value) {
  const afterDelete = deleteTextSelection(segment, cursor, selection);
  const text = segment.text || '';
  segment.text = text.slice(0, afterDelete.cursor) + value + text.slice(afterDelete.cursor);
  if (segment.kerning) segment.kerning.splice(afterDelete.cursor, 0, ...new Array(value.length).fill(0));
  adjustRangesForEdit(segment, afterDelete.cursor, value.length, 0);
  return { cursor: afterDelete.cursor + value.length, selection: null };
}

export function extendTextSelection(cursor, selection, position) {
  return {
    cursor: position,
    selection: selection ? { ...selection, end: position } : { start: cursor, end: position },
  };
}

export function cursorIndexFromPoint(positions, x, y, textLength) {
  if (!positions.length) return 0;
  let closestLine = 0;
  let lineDistance = Infinity;
  for (const position of positions) {
    const distance = Math.abs(y - (position.y + position.height / 2));
    if (distance < lineDistance) {
      lineDistance = distance;
      closestLine = position.lineIndex;
    }
  }
  let index = 0;
  let distance = Infinity;
  for (const position of positions) {
    if (position.lineIndex !== closestLine) continue;
    const left = Math.abs(x - position.x);
    const right = Math.abs(x - (position.x + position.width));
    if (left < distance) { distance = left; index = position.charIndex; }
    if (right < distance) { distance = right; index = position.charIndex + 1; }
  }
  return Math.max(0, Math.min(textLength, index));
}

export function verticalCursorIndex(positions, cursor, direction) {
  const current = positions.find(position => position.charIndex === cursor);
  if (!current) return cursor;
  const candidates = positions.filter(position => position.lineIndex === current.lineIndex + direction);
  if (!candidates.length) return cursor;
  return candidates.reduce((closest, candidate) => (
    Math.abs(current.x - candidate.x) < Math.abs(current.x - closest.x) ? candidate : closest
  )).charIndex;
}
