<script lang="ts" setup>
import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue';
import { FitAddon } from 'xterm-addon-fit';
import { Terminal } from 'xterm';
import 'xterm/css/xterm.css';
const emit = defineEmits(['update:value']);
const props = defineProps({
  /**终端ID，必传 */
  id: {
    type: String,
    required: true,
  },
  /**窗口单行字符数 */
  cols: {
    type: Number,
    default: 80,
  },
  /**窗口行数 */
  rows: {
    type: Number,
    default: 40,
  },
  /**信息 */
  value: {
    type: String,
    default: '',
  },
});

/**终端输入DOM节点实例对象 */
const terminalDom = ref<HTMLElement | undefined>(undefined);

/**终端输入实例对象 */
const terminal = ref<any>(null);

/**终端输入渲染 */
function handleRanderXterm(container: HTMLElement | undefined) {
  if (!container) return;
  const xterm = new Terminal({
    cols: props.cols,
    rows: props.rows,
    lineHeight: 1.2,
    fontSize: 12,
    fontFamily: "Monaco, Menlo, Consolas, 'Courier New', monospace",
    theme: {
      background: '#000000',
    },
    cursorBlink: false, // 光标闪烁
    cursorStyle: 'block',
    scrollback: 1000,
    scrollSensitivity: 15,
    tabStopWidth: 4,
    disableStdin: true, // 禁止输入
  });
  // 挂载
  xterm.open(container);
  // 自适应尺寸
  const fitAddon = new FitAddon();
  xterm.loadAddon(fitAddon);

  // 创建 ResizeObserver 实例
  var observer = new ResizeObserver(entries => {
    fitAddon.fit();
  });
  // 监听元素大小变化
  observer.observe(container);

  terminal.value = xterm;
}

onMounted(() => {
  nextTick(() => {
    handleRanderXterm(terminalDom.value);
    // 初始发送命令
    if (typeof props.value === 'string') {
      terminal.value.write(props.value);
    }
  });
});

onBeforeUnmount(() => {
  if (terminal.value != null) {
    terminal.value.dispose();
  }
});
</script>

<template>
  <div ref="terminalDom" :id="id" class="terminal"></div>
</template>

<style lang="css" scoped>
.terminal {
  width: 100%;
  height: 100%;
}
</style>
