import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef, NgZone, ElementRef, ViewChild, AfterViewInit, } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Router } from '@angular/router'; import { Subject, interval, Observable } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { animate, style, transition, trigger } from '@angular/animations'; import { default as autoAnimate } from '@formkit/auto-animate'; import { PopupService } from '../services/popup.service'; import { GameService } from '../services/game.service'; import { WinnerService } from '../services/winner.service'; import { JackpotService } from '../services/jackpot.service'; import { AnimationService } from '../services/animation.service'; @Component({ selector: 'app-landing', standalone: true, imports: [CommonModule], templateUrl: './landing.component.html', changeDetection: ChangeDetectionStrategy.OnPush, animations: [ trigger('fadeSlide', [ transition(':enter', [ style({ opacity: 0, transform: 'translateY(20px)' }), animate( '0.5s cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 1, transform: 'translateY(0)' }) ), ]), transition(':leave', [ animate( '0.5s cubic-bezier(0.4, 0, 0.2, 1)', style({ opacity: 0, transform: 'translateY(-20px)' }) ), ]), ]), ], }) export class LandingComponent implements OnInit, OnDestroy, AfterViewInit { private destroy$ = new Subject(); nearMiss = false; isScrolled = false; @ViewChild('jackpotCounter') jackpotCounter!: ElementRef; @ViewChild('heroSection') heroSection!: ElementRef; @ViewChild('gamesGrid') gamesGrid!: ElementRef; @ViewChild('winnersMarquee') winnersMarquee!: ElementRef; @ViewChild('particleContainer') particleContainer!: ElementRef; readonly showPopup$: Observable; readonly currentPopup$: Observable; readonly games$: Observable; readonly recentWinners$: Observable; readonly onlinePlayers$: Observable; readonly currentJackpot$: Observable; readonly timeLeft$: Observable; readonly totalPlayersToday: number; readonly totalWinnersToday: number; constructor( private router: Router, private cdr: ChangeDetectorRef, private ngZone: NgZone, private popupService: PopupService, private gameService: GameService, private winnerService: WinnerService, private jackpotService: JackpotService, private animationService: AnimationService ) { this.showPopup$ = this.popupService.showPopup$; this.currentPopup$ = this.popupService.currentPopup$; this.games$ = this.gameService.games$; this.recentWinners$ = this.winnerService.recentWinners$; this.onlinePlayers$ = this.winnerService.onlinePlayers$; this.currentJackpot$ = this.jackpotService.currentJackpot$; this.timeLeft$ = this.jackpotService.timeLeft$; this.totalPlayersToday = this.winnerService.getTotalPlayersToday(); this.totalWinnersToday = this.winnerService.getTotalWinnersToday(); } ngOnInit(): void { this.initializeTimers(); this.initializeScrollListener(); } ngAfterViewInit(): void { this.initializeAnimations(); } ngOnDestroy(): void { this.destroy$.next(); this.destroy$.complete(); window.removeEventListener('scroll', () => { this.isScrolled = window.scrollY > 0; }); } private initializeAnimations(): void { this.animationService.createParticleEffect(this.particleContainer); this.animationService.animateEntrance(this.heroSection); const gameCards = this.gamesGrid.nativeElement.querySelectorAll('.game-card'); gameCards.forEach((card: HTMLElement, index: number) => { this.animationService.animateEntrance(new ElementRef(card), 0.1 * index); }); autoAnimate(this.winnersMarquee.nativeElement); this.animationService.animateOnScroll(this.gamesGrid, 'slideUp'); this.currentJackpot$.pipe(takeUntil(this.destroy$)).subscribe((value) => { this.animationService.animateJackpotCounter(this.jackpotCounter, value - 1000, value); }); } private initializeTimers(): void { this.ngZone.runOutsideAngular(() => { interval(1500) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.jackpotService.updateJackpot(); this.cdr.markForCheck(); }); interval(3000) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.winnerService.updateOnlinePlayers(); this.cdr.markForCheck(); }); interval(1000) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.jackpotService.updateTimeLeft(); if (this.jackpotService.isUrgent()) { this.showUrgentOffer(); } this.cdr.markForCheck(); }); interval(7000) .pipe(takeUntil(this.destroy$)) .subscribe(() => { const randomGame = this.gameService.getGameById('mega-fortune'); if (randomGame) { const winAmount = Math.floor(Math.random() * 50000) + 10000; this.winnerService.generateNewWinner(randomGame.name, winAmount); if (winAmount > 10000) { this.showBigWinPopup(winAmount); } } this.cdr.markForCheck(); }); interval(15000) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.gameService.updateGameStats(); this.cdr.markForCheck(); }); interval(30000) .pipe(takeUntil(this.destroy$)) .subscribe(() => { this.popupService.showRandomPopup(); this.cdr.markForCheck(); }); }); } private initializeScrollListener(): void { window.addEventListener('scroll', () => { this.isScrolled = window.scrollY > 0; this.cdr.detectChanges(); }); } private showUrgentOffer(): void { this.popupService.showSpecificPopup({ title: '⚠️ LAST CHANCE!', message: 'Bonus offer expiring - Lock in 500% now!', type: 'urgent', cta: 'Claim Before Timer Ends', expires: '00:30', }); } private showBigWinPopup(amount: number): void { this.popupService.showSpecificPopup({ title: '🎰 MASSIVE WIN ALERT!', message: `Player just won €${amount.toLocaleString()} on minimum bet!`, subMessage: 'Same game still hot - Win rate increased to 99.9%!', type: 'win', cta: 'Play Same Game', }); } closePopup(): void { this.popupService.closePopup(); } claimBonus(): void { this.nearMiss = true; this.cdr.markForCheck(); setTimeout(() => { this.router.navigate(['/register'], { queryParams: { bonus: 'welcome1000', ref: 'landing_hero', special: 'true', vip: 'fast-track', }, }); }, 1500); } playNow(gameId: string): void { const game = this.gameService.getGameById(gameId); if (!game) return; this.popupService.showSpecificPopup({ title: '🎰 PERFECT TIMING!', message: `${game.name} is currently at ${game.winChance}% win rate!`, subMessage: `Last player won €${game.lastWin.toLocaleString()} - Hot streak active!`, type: 'fomo', cta: 'Play Now', }); setTimeout(() => { this.router.navigate(['/game', gameId], { queryParams: { ref: 'landing_games', bonus: 'true', rtp: 'enhanced', multiplier: 'active', }, }); }, 2000); } onButtonClick(event: MouseEvent): void { const button = event.currentTarget as HTMLElement; this.animationService.animateButtonClick(new ElementRef(button)); } onGameCardHover(event: MouseEvent): void { const card = event.currentTarget as HTMLElement; this.animationService.animateFloat(new ElementRef(card)); } }