import { NjetComponent} from "/njet.js"

    class NjetEditor extends NjetComponent {
      constructor() {
        super();
        this.attachShadow({ mode: 'open' });

        const style = document.createElement('style');
        style.textContent = `
          #editor {
            padding: 1rem;
            outline: none;
            white-space: pre-wrap;
            line-height: 1.5;
            height: 100%;
            overflow-y: auto;
            background: #1e1e1e;
            color: #d4d4d4;
          }
          #command-line {
            position: absolute;
            bottom: 0;
            left: 0;
            width: 100%;
            padding: 0.2rem 1rem;
            background: #333;
            color: #0f0;
            display: none;
            font-family: monospace;
          }
        `;

        this.editor = document.createElement('div');
        this.editor.id = 'editor';
        this.editor.contentEditable = true;
        this.editor.innerText = `Welcome to VimEditor Component
Line 2 here
Another line
Try i, Esc, v, :, yy, dd, 0, $, gg, G, and p`;

        this.cmdLine = document.createElement('div');
        this.cmdLine.id = 'command-line';
        this.shadowRoot.append(style, this.editor, this.cmdLine);

        this.mode = 'normal'; // normal | insert | visual | command
        this.keyBuffer = '';
        this.lastDeletedLine = '';
        this.yankedLine = '';

        this.editor.addEventListener('keydown', this.handleKeydown.bind(this));
      }

      connectedCallback() {
        this.editor.focus();
      }

      getCaretOffset() {
        let caretOffset = 0;
        const sel = this.shadowRoot.getSelection();
        if (!sel || sel.rangeCount === 0) return 0;

        const range = sel.getRangeAt(0);
        const preCaretRange = range.cloneRange();
        preCaretRange.selectNodeContents(this.editor);
        preCaretRange.setEnd(range.endContainer, range.endOffset);
        caretOffset = preCaretRange.toString().length;
        return caretOffset;
      }

      setCaretOffset(offset) {
        const range = document.createRange();
        const sel = this.shadowRoot.getSelection();
        const walker = document.createTreeWalker(this.editor, NodeFilter.SHOW_TEXT, null, false);

        let currentOffset = 0;
        let node;
        while ((node = walker.nextNode())) {
          if (currentOffset + node.length >= offset) {
            range.setStart(node, offset - currentOffset);
            range.collapse(true);
            sel.removeAllRanges();
            sel.addRange(range);
            return;
          }
          currentOffset += node.length;
        }
      }

      handleKeydown(e) {
        const key = e.key;

        if (this.mode === 'insert') {
          if (key === 'Escape') {
            e.preventDefault();
            this.mode = 'normal';
            this.editor.blur();
            this.editor.focus();
          }
          return;
        }

        if (this.mode === 'command') {
          if (key === 'Enter' || key === 'Escape') {
            e.preventDefault();
            this.cmdLine.style.display = 'none';
            this.mode = 'normal';
            this.keyBuffer = '';
          }
          return;
        }

        if (this.mode === 'visual') {
          if (key === 'Escape') {
            e.preventDefault();
            this.mode = 'normal';
          }
          return;
        }

        // Handle normal mode
        this.keyBuffer += key;

        const text = this.editor.innerText;
        const caretPos = this.getCaretOffset();
        const lines = text.split('\n');

        let charCount = 0, lineIdx = 0;
        for (let i = 0; i < lines.length; i++) {
          if (caretPos <= charCount + lines[i].length) {
            lineIdx = i;
            break;
          }
          charCount += lines[i].length + 1;
        }

        const offsetToLine = idx =>
          text.split('\n').slice(0, idx).reduce((acc, l) => acc + l.length + 1, 0);

        switch (this.keyBuffer) {
          case 'i':
            e.preventDefault();
            this.mode = 'insert';
            this.keyBuffer = '';
            break;

          case 'v':
            e.preventDefault();
            this.mode = 'visual';
            this.keyBuffer = '';
            break;

          case ':':
            e.preventDefault();
            this.mode = 'command';
            this.cmdLine.style.display = 'block';
            this.cmdLine.textContent = ':';
            this.keyBuffer = '';
            break;

          case 'yy':
            e.preventDefault();
            this.yankedLine = lines[lineIdx];
            this.keyBuffer = '';
            break;

          case 'dd':
            e.preventDefault();
            this.lastDeletedLine = lines[lineIdx];
            lines.splice(lineIdx, 1);
            this.editor.innerText = lines.join('\n');
            this.setCaretOffset(offsetToLine(lineIdx));
            this.keyBuffer = '';
            break;

          case 'p':
            e.preventDefault();
            const lineToPaste = this.yankedLine || this.lastDeletedLine;
            if (lineToPaste) {
              lines.splice(lineIdx + 1, 0, lineToPaste);
              this.editor.innerText = lines.join('\n');
              this.setCaretOffset(offsetToLine(lineIdx + 1));
            }
            this.keyBuffer = '';
            break;

          case '0':
            e.preventDefault();
            this.setCaretOffset(offsetToLine(lineIdx));
            this.keyBuffer = '';
            break;

          case '$':
            e.preventDefault();
            this.setCaretOffset(offsetToLine(lineIdx) + lines[lineIdx].length);
            this.keyBuffer = '';
            break;

          case 'gg':
            e.preventDefault();
            this.setCaretOffset(0);
            this.keyBuffer = '';
            break;

          case 'G':
            e.preventDefault();
            this.setCaretOffset(text.length);
            this.keyBuffer = '';
            break;

          case 'Escape':
            e.preventDefault();
            this.mode = 'normal';
            this.keyBuffer = '';
            this.cmdLine.style.display = 'none';
            break;

          default:
            // allow up to 2 chars for combos
            if (this.keyBuffer.length > 2) this.keyBuffer = '';
            break;
        }
      }
    }

    customElements.define('njet-editor', NjetEditor);
export {NjetEditor}
