Source: app/composables/useParenHighlightLayer.js

/*
 * Copyright 2026 The Ray Optics Simulation authors and contributors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ref, computed, onMounted, onBeforeUnmount } from 'vue'
import {
  findMatchingParenPair,
  buildParenHighlightHtml
} from '../utils/parenHighlightHtml.js'

/**
 * Matching-parenthesis overlay for a textarea (pair with a highlight layer + shared CSS).
 *
 * @param {function(): *} getTextareaRef - Returns the textarea element or null/undefined.
 * @param {function(): string} getText
 * @param {function(): boolean} isFieldActive - True when the field is focused.
 */
export function useParenHighlightLayer(getTextareaRef, getText, isFieldActive) {
  const parenMatchPair = ref(null)

  const highlightLayerHtml = computed(() =>
    buildParenHighlightHtml(getText(), parenMatchPair.value)
  )

  const updateParenHighlight = () => {
    const el = getTextareaRef()
    if (!el || !isFieldActive()) {
      parenMatchPair.value = null
      return
    }
    const caret = el.selectionStart ?? 0
    parenMatchPair.value = findMatchingParenPair(getText(), caret)
  }

  const clearParenHighlight = () => {
    parenMatchPair.value = null
  }

  const onDocumentSelectionChange = () => {
    if (document.activeElement === getTextareaRef()) {
      updateParenHighlight()
    }
  }

  onMounted(() => {
    document.addEventListener('selectionchange', onDocumentSelectionChange)
  })

  onBeforeUnmount(() => {
    document.removeEventListener('selectionchange', onDocumentSelectionChange)
  })

  return {
    highlightLayerHtml,
    updateParenHighlight,
    clearParenHighlight
  }
}