<template>
  <div
    class="sh-field position-relative"
    :class="{
      'sh-field--disabled': disabled,
      'sh-field--empty': !modelValue,
      'sh-field--large': size === 'large',
    }"
  >
    <div
      v-if="modelValue"
      class="sh-field__highlight font-mono"
      :class="multiline ? 'sh-field__highlight--multi' : 'sh-field__highlight--single'"
      aria-hidden="true"
      v-html="highlighted"
    />
    <component
      :is="multiline ? 'textarea' : 'input'"
      :value="modelValue"
      :placeholder="placeholder"
      :disabled="disabled"
      :rows="multiline ? rows : undefined"
      class="sh-field__input font-mono"
      :class="multiline ? 'sh-field__input--multi' : 'sh-field__input--single'"
      spellcheck="false"
      autocomplete="off"
      @input="onInput"
      @keydown="onKeydown"
    />
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { highlightShellToHtml } from '@/utils/shellHighlight'

const props = withDefaults(
  defineProps<{
    modelValue: string
    placeholder?: string
    disabled?: boolean
    multiline?: boolean
    rows?: number
    size?: 'default' | 'large'
  }>(),
  {
    placeholder: '',
    disabled: false,
    multiline: false,
    rows: 3,
    size: 'default',
  },
)

const emit = defineEmits<{
  'update:modelValue': [value: string]
  keydown: [event: KeyboardEvent]
}>()

const highlighted = computed(() => highlightShellToHtml(props.modelValue))

function onInput(e: Event) {
  const el = e.target as HTMLInputElement | HTMLTextAreaElement
  emit('update:modelValue', el.value)
}

function onKeydown(e: KeyboardEvent) {
  emit('keydown', e)
}
</script>

<style scoped>
.sh-field__highlight,
.sh-field__input {
  font-size: 0.875rem;
  line-height: 1.5;
  padding: 8px 12px;
  border-radius: 4px;
  width: 100%;
  box-sizing: border-box;
  font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', Menlo, monospace;
}

.sh-field__highlight--single,
.sh-field__input--single {
  min-height: 36px;
}

.sh-field__highlight--multi,
.sh-field__input--multi {
  min-height: 72px;
  resize: vertical;
}

.sh-field__highlight {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
  white-space: pre-wrap;
  word-break: break-word;
  overflow: hidden;
  border: 1px solid transparent;
}

.sh-field__input {
  position: relative;
  z-index: 2;
  background: transparent;
  color: transparent;
  caret-color: rgb(var(--v-theme-primary));
  border: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
  outline: none;
}

.sh-field__input:focus {
  border-color: rgb(var(--v-theme-primary));
}

.sh-field--disabled .sh-field__input {
  opacity: 0.5;
  pointer-events: none;
}

.sh-field--empty .sh-field__input {
  color: rgba(var(--v-theme-on-surface), 0.42);
}

.sh-field:not(.sh-field--empty) .sh-field__input {
  color: transparent;
}

.sh-field--large .sh-field__highlight,
.sh-field--large .sh-field__input {
  font-size: 1rem;
  line-height: 1.55;
  padding: 12px 14px;
}

.sh-field--large .sh-field__input--single {
  min-height: 108px;
}

.sh-field--large .sh-field__highlight--single {
  min-height: 108px;
}

.sh-field--large .sh-field__input--multi {
  min-height: 108px;
}

.sh-field--large .sh-field__highlight--multi {
  min-height: 108px;
}
</style>
