import { Component, OnInit, OnDestroy } from '@angular/core';
import { HoloVideoContainerComponent } from '../../components/holo-video-container/holo-video-container.component';

@Component({
  selector: 'app-hero',
  imports: [HoloVideoContainerComponent],
  templateUrl: './hero.component.html',
  styleUrl: './hero.component.css',
})
export class HeroComponent implements OnInit, OnDestroy {
  displayText: string = '';
  nameText: string = '';

  private messageQueue: string[] = [
    'Web Developer',
    'Coding Enjoyer',
    'Software Artisan',
  ];

  private currentMessage: string = '';
  private currentName: string = 'ADAM\nBENYEKKOU';
  private isGlitching: boolean = false;
  private isNameGlitching: boolean = false;
  private frameRequest: number | null = null;
  private nameFrameRequest: number | null = null;
  private processTimeout: any = null;
  private isInitialMount: boolean = true;

  ngOnInit(): void {
    this.initialMountAnimation();
  }

  ngOnDestroy(): void {
    this.cleanup();
  }

  private cleanup(): void {
    if (this.frameRequest) {
      cancelAnimationFrame(this.frameRequest);
    }
    if (this.nameFrameRequest) {
      cancelAnimationFrame(this.nameFrameRequest);
    }
    if (this.processTimeout) {
      clearTimeout(this.processTimeout);
    }
  }

  private initialMountAnimation(): void {
    // Start both animations simultaneously
    this.animateNameOnInit();
    this.animateDisplayTextOnInit();
  }

  private animateNameOnInit(): void {
    const targetName = this.currentName;
    let currentIndex = 0;

    const animateNextLetter = (): void => {
      if (currentIndex <= targetName.length) {
        let output = '';

        // Build the confirmed part
        for (let i = 0; i < currentIndex; i++) {
          output += targetName[i];
        }

        // Add intense scrambling for upcoming letters
        const scrambleLength = Math.min(8, targetName.length - currentIndex);
        for (let i = 0; i < scrambleLength; i++) {
          output += Math.random() > 0.5 ? '0' : '1';
        }

        this.nameText = output;

        if (currentIndex < targetName.length) {
          currentIndex++;
          setTimeout(animateNextLetter, 45 + Math.random() * 35); // Slightly slower for name
        } else {
          // Name animation complete, start glitching
          this.nameText = targetName;
          this.isNameGlitching = true;
          this.glitchName();
        }
      }
    };

    animateNextLetter();
  }

  private animateDisplayTextOnInit(): void {
    const firstMessage = this.messageQueue[0];
    let currentIndex = 0;

    const animateNextLetter = (): void => {
      if (currentIndex <= firstMessage.length) {
        let output = '';

        // Build the confirmed part
        for (let i = 0; i < currentIndex; i++) {
          output += firstMessage[i];
        }

        // Add intense scrambling for upcoming letters
        const scrambleLength = Math.min(6, firstMessage.length - currentIndex);
        for (let i = 0; i < scrambleLength; i++) {
          output += Math.random() > 0.5 ? '0' : '1';
        }

        this.displayText = output;

        if (currentIndex < firstMessage.length) {
          currentIndex++;
          setTimeout(animateNextLetter, 35 + Math.random() * 25);
        } else {
          // Mount animation complete, start normal cycle
          this.displayText = firstMessage;
          this.currentMessage = firstMessage;
          this.messageQueue.shift();
          this.isInitialMount = false;

          // Start the regular cycle after a short pause
          setTimeout(() => {
            this.processQueue();
          }, 2000);
        }
      }
    };

    animateNextLetter();
  }

  private processQueue(): void {
    if (this.messageQueue.length === 0) {
      this.messageQueue = [
        'Web Developer',
        'Coding Enjoyer',
        'Software Artisan',
      ];
    }

    const nextMessage = this.messageQueue.shift()!;
    this.startScrambleAnimation(nextMessage);

    this.processTimeout = setTimeout(() => {
      this.processQueue();
    }, 6000);
  }

  private startScrambleAnimation(nextMessage: string): void {
    const length = Math.max(this.displayText.length, nextMessage.length);
    let complete = 0;

    const update = (): void => {
      let output = '';
      const scrambleChars = 3 + Math.random() * 5;

      for (let i = 0; i < length; i++) {
        const scramble = i < scrambleChars + complete && Math.random() > 0.8;

        if (i < nextMessage.length) {
          if (scramble) {
            output += Math.random() > 0.5 ? '0' : '1';
          } else if (i < complete) {
            output += nextMessage[i];
          } else {
            output += this.displayText[i] || (Math.random() > 0.5 ? '0' : '1');
          }
        }
      }

      this.displayText = output;

      if (complete < nextMessage.length) {
        complete += 0.5 + Math.floor(Math.random() * 2);
        setTimeout(update, 40 + Math.random() * 60);
      } else {
        this.displayText = nextMessage;
        this.currentMessage = nextMessage;
        this.isGlitching = true;
        this.glitchText();
      }
    };

    this.isGlitching = false;
    if (this.frameRequest) {
      cancelAnimationFrame(this.frameRequest);
    }
    update();
  }

  private glitchText(): void {
    if (!this.isGlitching) return;

    const probability = Math.random();

    if (probability < 0.05) {
      const scrambledText = this.currentMessage
        .split('')
        .map(() => (Math.random() > 0.5 ? '0' : '1'))
        .join('');
      this.displayText = scrambledText;

      setTimeout(() => {
        this.displayText = this.currentMessage;
      }, 25);
    } else if (probability < 0.15) {
      const textArray = this.currentMessage.split('');
      for (let i = 0; i < Math.floor(textArray.length * 0.2); i++) {
        const idx = Math.floor(Math.random() * textArray.length);
        textArray[idx] = Math.random() > 0.5 ? '0' : '1';
      }
      this.displayText = textArray.join('');

      setTimeout(() => {
        this.displayText = this.currentMessage;
      }, 20);
    }

    const jitterProbability = Math.random();
    if (jitterProbability < 0.1) {
      setTimeout(() => {
        const textArray = this.displayText.split('');
        for (let i = 0; i < 2; i++) {
          const idx = Math.floor(Math.random() * textArray.length);
          if (textArray[idx] === '0' || textArray[idx] === '1') {
            textArray[idx] = textArray[idx] === '0' ? '1' : '0';
          }
        }
        this.displayText = textArray.join('');

        setTimeout(() => {
          this.displayText = this.currentMessage;
        }, 15);
      }, 15);
    }

    this.frameRequest = requestAnimationFrame(() => {
      setTimeout(() => this.glitchText(), Math.random() * 500);
    });
  }

  private glitchName(): void {
    if (!this.isNameGlitching) return;

    const probability = Math.random();

    if (probability < 0.03) {
      // Less frequent than displayText glitching
      const scrambledName = this.currentName
        .split('')
        .map((char) => (char === '\n' ? '\n' : Math.random() > 0.5 ? '0' : '1'))
        .join('');
      this.nameText = scrambledName;

      setTimeout(() => {
        this.nameText = this.currentName;
      }, 30);
    } else if (probability < 0.08) {
      const nameArray = this.currentName.split('');
      for (let i = 0; i < Math.floor(nameArray.length * 0.15); i++) {
        const idx = Math.floor(Math.random() * nameArray.length);
        if (nameArray[idx] !== '\n') {
          // Don't replace line breaks
          nameArray[idx] = Math.random() > 0.5 ? '0' : '1';
        }
      }
      this.nameText = nameArray.join('');

      setTimeout(() => {
        this.nameText = this.currentName;
      }, 25);
    }

    // Subtle character jitter
    const jitterProbability = Math.random();
    if (jitterProbability < 0.05) {
      setTimeout(() => {
        const nameArray = this.nameText.split('');
        for (let i = 0; i < 1; i++) {
          // Just 1 character at a time for name
          const idx = Math.floor(Math.random() * nameArray.length);
          if (nameArray[idx] === '0' || nameArray[idx] === '1') {
            nameArray[idx] = nameArray[idx] === '0' ? '1' : '0';
          }
        }
        this.nameText = nameArray.join('');

        setTimeout(() => {
          this.nameText = this.currentName;
        }, 20);
      }, 20);
    }

    this.nameFrameRequest = requestAnimationFrame(() => {
      setTimeout(() => this.glitchName(), Math.random() * 800); // Slower glitching for name
    });
  }
}
