import { ChangeDetectionStrategy, Component, inject, signal, OnInit } from '@angular/core'; import { CommonModule } from '@angular/common'; import { Router } from '@angular/router'; import { PlayingCardComponent } from './components/playing-card/playing-card.component'; import { DealerHandComponent } from './components/dealer-hand/dealer-hand.component'; import { PlayerHandComponent } from './components/player-hand/player-hand.component'; import { GameControlsComponent } from './components/game-controls/game-controls.component'; import { GameInfoComponent } from './components/game-info/game-info.component'; import { Card, BlackjackGame } from '@blackjack/models/blackjack.model'; import { BlackjackService } from '@blackjack/services/blackjack.service'; import { HttpErrorResponse } from '@angular/common/http'; import { GameResultComponent } from '@blackjack/components/game-result/game-result.component'; import { GameState } from '@blackjack/enum/gameState'; import { NavbarComponent } from '@shared/components/navbar/navbar.component'; import { UserService } from '@service/user.service'; import { timer } from 'rxjs'; import { DebtDialogComponent } from '@shared/components/debt-dialog/debt-dialog.component'; @Component({ selector: 'app-blackjack', standalone: true, imports: [ CommonModule, NavbarComponent, PlayingCardComponent, DealerHandComponent, PlayerHandComponent, GameControlsComponent, GameInfoComponent, GameResultComponent, DebtDialogComponent, ], templateUrl: './blackjack.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) export default class BlackjackComponent implements OnInit { private router = inject(Router); private userService = inject(UserService); private blackjackService = inject(BlackjackService); dealerCards = signal([]); playerCards = signal([]); currentBet = signal(0); balance = signal(0); currentGameId = signal(undefined); gameInProgress = signal(false); gameState = signal(GameState.IN_PROGRESS); showGameResult = signal(false); isActionInProgress = signal(false); showDebtDialog = signal(false); debtAmount = signal(0); ngOnInit(): void { this.userService.currentUser$.subscribe((user) => { if (user) { this.balance.set(user.balance); } }); } private updateGameState(game: BlackjackGame) { console.log('Game state update:', game); this.currentGameId.set(game.id); this.currentBet.set(game.bet); this.gameInProgress.set(game.state === GameState.IN_PROGRESS); this.gameState.set(game.state as GameState); const isGameOver = game.state !== GameState.IN_PROGRESS; this.dealerCards.set( game.dealerCards.map((card, index) => ({ ...card, hidden: !isGameOver && index === 1 && game.state === GameState.IN_PROGRESS, })) ); this.playerCards.set( game.playerCards.map((card) => ({ ...card, hidden: false, })) ); if (isGameOver) { console.log('Game is over, state:', game.state); this.userService.refreshCurrentUser(); timer(1500).subscribe(() => { this.showGameResult.set(true); console.log('Game result dialog shown after delay'); }); } } onNewGame(bet: number): void { this.isActionInProgress.set(true); this.blackjackService.startGame(bet).subscribe({ next: (game) => { this.updateGameState(game); this.userService.refreshCurrentUser(); this.isActionInProgress.set(false); }, error: (error) => { console.error('Failed to start game:', error); this.isActionInProgress.set(false); }, }); } onHit(): void { if (!this.currentGameId() || this.isActionInProgress()) return; this.isActionInProgress.set(true); this.blackjackService.hit(this.currentGameId()!).subscribe({ next: (game) => { this.updateGameState(game); if (game.state !== 'IN_PROGRESS') { this.userService.refreshCurrentUser(); } this.isActionInProgress.set(false); }, error: (error) => { console.error('Failed to hit:', error); this.handleGameError(error); this.isActionInProgress.set(false); }, }); } onStand(): void { if (!this.currentGameId() || this.isActionInProgress()) return; if (this.gameState() !== GameState.IN_PROGRESS) { console.log('Cannot stand: game is not in progress'); return; } this.isActionInProgress.set(true); this.blackjackService.stand(this.currentGameId()!).subscribe({ next: (game) => { this.updateGameState(game); this.userService.refreshCurrentUser(); this.isActionInProgress.set(false); }, error: (error) => { console.error('Failed to stand:', error); this.handleGameError(error); this.isActionInProgress.set(false); }, }); } onDoubleDown(): void { if (!this.currentGameId() || this.isActionInProgress()) return; if (this.gameState() !== GameState.IN_PROGRESS || this.playerCards().length !== 2) { console.log('Cannot double down: game is not in progress or more than 2 cards'); return; } this.isActionInProgress.set(true); this.blackjackService.doubleDown(this.currentGameId()!).subscribe({ next: (game) => { this.updateGameState(game); this.userService.getCurrentUser().subscribe((user) => { if (user && user.balance < 0) { this.debtAmount.set(Math.abs(user.balance)); this.showDebtDialog.set(true); } }); this.isActionInProgress.set(false); }, error: (error) => { console.error('Failed to double down:', error); this.handleGameError(error); this.isActionInProgress.set(false); }, }); } onCloseGameResult(): void { console.log('Closing game result dialog'); this.showGameResult.set(false); this.userService.refreshCurrentUser(); } onCloseDebtDialog(): void { this.showDebtDialog.set(false); } private handleGameError(error: HttpErrorResponse): void { if (error instanceof HttpErrorResponse) { if (error.status === 400 && error.error?.error === 'Invalid state') { this.gameInProgress.set(false); this.userService.refreshCurrentUser(); } else if (error.status === 500) { console.log('Server error occurred. The game may have been updated in another session.'); this.gameInProgress.set(false); this.userService.refreshCurrentUser(); if (this.currentGameId()) { this.refreshGameState(this.currentGameId()!); } } } } private refreshGameState(gameId: number): void { this.blackjackService.getGame(gameId).subscribe({ next: (game) => { this.updateGameState(game); }, error: (err) => { console.error('Failed to refresh game state:', err); }, }); } leaveGame(): void { this.router.navigate(['/home']); } }