import {Directive, ElementRef, Input, OnChanges, SimpleChanges} from '@angular/core';
import {Utils} from '../../utils/utils.util';

@Directive({
  selector: '[njHighlight]',
  standalone: true
})
export class HighlightDirective implements OnChanges {
  /**
   * Content we want to highlight
   */
  @Input()
  public content: string;

  /**
   * Text to highlight in the content
   */
  @Input()
  public textToHighlight: string;

  /**
   * Whether to escape accents or no
   */
  @Input()
  public escapeAccents = true;

  /**
   * Whether to take into account case or no
   */
  @Input()
  public caseSensitive = false;

  private readonly OPENING_TAG = '<mark class="nj-highlight">';
  private readonly CLOSING_TAG = '</mark>';

  constructor(private el: ElementRef) {}

  ngOnChanges(changes: SimpleChanges) {
    this.highlightText();
  }

  private highlightText(): void {
    if (Utils.isUndefinedOrNull(this.content) || Utils.isUndefinedOrNull(this.el?.nativeElement)) {
      return;
    }
    const regexFlags = this.caseSensitive ? 'g' : 'gi';
    let innerHtml: string;
    if (Utils.isUndefinedOrNull(this.textToHighlight)) {
      innerHtml = this.content;
    } else {
      if (this.escapeAccents) {
        const regExp = new RegExp(Utils.normalizeString(this.textToHighlight), regexFlags);
        const matches = Utils.normalizeString(this.content).matchAll(regExp);
        let finalText = this.content;
        let buffer = 0;
        if (!Utils.isUndefinedOrNull(matches)) {
          for (const match of matches) {
            const updatedIndex = buffer + match.index;
            const textBeforeOccurrence = finalText.slice(0, updatedIndex);
            const occurrence = finalText.slice(updatedIndex, updatedIndex + this.textToHighlight.length);
            const textAfterOccurrence = finalText.slice(updatedIndex + this.textToHighlight.length, finalText.length);
            finalText = `${textBeforeOccurrence}${this.OPENING_TAG}${occurrence}${this.CLOSING_TAG}${textAfterOccurrence}`;
            buffer = buffer + this.OPENING_TAG.length + this.CLOSING_TAG.length;
          }
        }
        innerHtml = finalText;
      } else {
        const regExp = new RegExp(this.textToHighlight, regexFlags);
        innerHtml = this.content.replace(regExp, `${this.OPENING_TAG}$&${this.CLOSING_TAG}`);
      }
    }
    this.el.nativeElement.innerHTML = innerHtml;
  }
}
