using Minesweeper.Commands; using Minesweeper.Core; using Minesweeper.Presentation.ReadModels; using Minesweeper.Presentation.Views; namespace Minesweeper.Presentation.Presenters { public sealed class GamePresenter : IPresenter { private readonly IGameCommandDispatcher commandDispatcher; private readonly IGamePauseService pauseService; private readonly IGameReadModel readModel; private readonly IGameStateService gameStateService; private readonly IGameTimerService timerService; private readonly IGameView view; private bool boardBuilt; public GamePresenter(IGameCommandDispatcher commandDispatcher, IGamePauseService pauseService, IGameReadModel readModel, IGameStateService gameStateService, IGameTimerService timerService, IGameView view = null) { this.commandDispatcher = commandDispatcher; this.pauseService = pauseService; this.readModel = readModel; this.gameStateService = gameStateService; this.timerService = timerService; this.view = view; } public void Initialize() { if (view != null) { view.RestartRequested += OnRestartRequested; view.GoToMenuRequested += OnGoToMenuRequested; view.PauseRequested += OnPauseRequested; view.ResumeRequested += OnResumeRequested; view.CellOpenRequested += OnCellOpenRequested; view.CellFlagRequested += OnCellFlagRequested; gameStateService.StateChanged += OnStateChanged; pauseService.PauseChanged += OnPauseChanged; timerService.TimeChanged += OnTimeChanged; OnStateChanged(gameStateService.Current); OnPauseChanged(pauseService.IsPaused); OnTimeChanged(timerService.ElapsedSeconds); } } public void Dispose() { if (view != null) { view.RestartRequested -= OnRestartRequested; view.GoToMenuRequested -= OnGoToMenuRequested; view.PauseRequested -= OnPauseRequested; view.ResumeRequested -= OnResumeRequested; view.CellOpenRequested -= OnCellOpenRequested; view.CellFlagRequested -= OnCellFlagRequested; gameStateService.StateChanged -= OnStateChanged; pauseService.PauseChanged -= OnPauseChanged; timerService.TimeChanged -= OnTimeChanged; } } private void OnRestartRequested() { commandDispatcher.Dispatch(new RestartCommand()); RebuildBoard(); } private void OnGoToMenuRequested() { commandDispatcher.Dispatch(new GoToMenuCommand()); } private void OnPauseRequested() { commandDispatcher.Dispatch(new PauseCommand()); } private void OnResumeRequested() { commandDispatcher.Dispatch(new ResumeCommand()); } private void OnCellOpenRequested(int x, int y) { commandDispatcher.Dispatch(new OpenCellCommand(x, y)); RefreshBoard(); UpdateBoardInput(); } private void OnCellFlagRequested(int x, int y) { commandDispatcher.Dispatch(new ToggleFlagCommand(x, y)); RefreshBoard(); UpdateBoardInput(); } private void OnStateChanged(GameState state) { if (state == GameState.FieldSelection) { boardBuilt = false; view.HideGame(); view.HidePause(); return; } view.ShowGame(); if (!boardBuilt || state == GameState.Preparing) { RebuildBoard(); } else { RefreshBoard(); } UpdateBoardInput(); } private void OnPauseChanged(bool isPaused) { if (isPaused) { view.ShowPause(); } else { view.HidePause(); } UpdateBoardInput(); } private void OnTimeChanged(float seconds) { view.SetTimer(seconds); } private void RebuildBoard() { var cells = readModel.GetCells(); view.SetMineCount(readModel.MinesCount); view.RebuildBoard(cells, readModel.Width, readModel.Height); boardBuilt = true; UpdateBoardInput(); } private void RefreshBoard() { view.RefreshBoard(readModel.GetCells()); } private void UpdateBoardInput() { var state = gameStateService.Current; view.SetBoardInputEnabled(!pauseService.IsPaused && (state == GameState.Preparing || state == GameState.Playing)); } } }