import { Directive, ElementRef, Input, OnDestroy, AfterViewInit  } from '@angular/core';
import * as ace from 'ace-builds';
//import 'ace-builds/src-min/ext-language_tools';

// Import ace's Range module
const Range = ace.require('ace/range').Range;


@Directive({
  selector: '[appAceEditor]'
})
export class AceEditorDirective implements AfterViewInit , OnDestroy {
  private editor: any;
  private markers: number[] = []; // Array to keep track of markers

  @Input() set appAceEditor(content: string) {
    if (this.editor) {
      this.editor.setValue(content, -1); // Load content into the editor
    }
  }

  @Input() set appAceEditorPreview(content: string) {
    if (this.editor && content) {
      this.editor.setValue(content, -1); // Set the preview content
    }
  }

  constructor(public el: ElementRef) {}

  ngAfterViewInit() {
    ace.config.set('basePath', 'node_modules/ace-builds/src-min/');
    this.editor = ace.edit(this.el.nativeElement);

    this.editor.setOptions({
      theme: 'ace/theme/monokai',
      mode: 'ace/mode/xml',
     // showLineNumbers: true, 
     // showGutter: false, 
     // highlightActiveLine: false, 
      showPrintMargin: false,
      enableLiveAutocompletion: true,
      enableBasicAutocompletion: true,
      enableSnippets: true
    });

    const langTools = ace.require('ace/ext/language_tools');
  if (langTools) {
    langTools.setCompleters([
      {
        getCompletions(editor, session, pos, prefix, callback) {
          // Custom autocompletion logic
          callback(null, [
            { caption: 'example', value: 'example', meta: 'example' },
          ]);
        },
      },
    ]);
  } else {
    console.error('Language tools module not found.');
  }

 // this.validateTags();

 // this.editor.on('change', () => this.validateTags());

  // Add event listener for the 'change' event
 // this.editor.on('change', (delta: any) => {
   // if (delta.action === 'insert' && delta.lines[0] === '>') {
   //   this.handleAutoCloseTag();
   // }
  //});

  

  }

  private validateTags(): void {
    //debugger;
    const value = this.editor.getValue();
    const errors: ace.Ace.Annotation[] = [];
    const tagStack: { tag: string; line: number }[] = [];
    const tagRegex = /<\/?([a-zA-Z0-9\-]+)(\s*[^>]*)?>|<\/([a-zA-Z0-9\-]+)>/g;

    const lines = value.split('\n');
    lines.forEach((line, lineNumber) => {
      let match;
      while ((match = tagRegex.exec(line))) {
        const [fullTag, openingTag, selfClosing, closingTag] = match;

        if (selfClosing && fullTag.endsWith('/>')) {
          // Self-closing tag, no need to track
          continue;
        }

        if (openingTag && !fullTag.startsWith('</')) {
          // Opening tag: Push to stack
          tagStack.push({ tag: openingTag, line: lineNumber });
        } else if (closingTag) {
          // Closing tag: Match with stack
          const lastTag = tagStack.pop();
          if (!lastTag || lastTag.tag !== closingTag) {
            // Mismatch or unexpected closing tag
            errors.push({
              row: lineNumber,
              column: line.indexOf(fullTag),
              text: `Unexpected closing tag </${closingTag}> or no matching opening tag.`,
              type: 'error',
            });
          }
        }
      }
    });

    // Unclosed tags remaining in stack
    tagStack.forEach(({ tag, line }) => {
      errors.push({
        row: line,
        column: lines[line].indexOf(`<${tag}`),
        text: `Unclosed opening tag <${tag}>.`,
        type: 'error',
      });
    });

    this.editor.session.setAnnotations(errors);
  }
  

  ngOnDestroy() {
    if (this.editor) {
      this.editor.destroy();
      this.editor = null;
    }
  }

  highlightMatch(patternResults: any[]) {
    this.clearMarkers();
    patternResults.forEach((patternResult) => {
      patternResult.matches.forEach((match) => {
        const startIndex = this.editor.getSession().doc.indexToPosition(match.index);
        const endIndex = this.editor.getSession().doc.indexToPosition(match.index + match.content.length);
        const range = new Range(startIndex.row, startIndex.column, endIndex.row, endIndex.column);
        const markerId = this.editor.getSession().addMarker(range, 'highlight', 'text');
        this.markers.push(markerId);
      });
    });
  }

  clearMarkers() {
    this.markers.forEach(markerId => {
      this.editor.getSession().removeMarker(markerId);
    });
    this.markers = [];
  }

  getEditorContent(): string {
    return this.editor.getValue();
  }

  updateEditorContent(content: string) {
    if (this.editor) {
      this.editor.setValue(content, -1);
    }
  }

  private handleAutoCloseTag() {
    const cursor = this.editor.getCursorPosition();
    const line = this.editor.session.getLine(cursor.row);
    const match = line.substring(0, cursor.column).match(/<(\w+)([^>]*)>$/);

    if (match) {
      const tagName = match[1];
      const closingTag = `</${tagName}>`;
      this.editor.insert(closingTag);
      this.editor.navigateLeft(closingTag.length); // Move cursor inside the closing tag
    }
  }
}
