using Minesweeper.Commands; using Minesweeper.Core; using Minesweeper.Presentation.Factories; using Minesweeper.Presentation.ReadModels; using Minesweeper.Presentation.Views; namespace Minesweeper.Presentation.Presenters { public sealed class GamePresenter : IPresenter { private readonly IGameCommandDispatcher commandDispatcher; private readonly ICellViewFactory cellViewFactory; private readonly IGamePauseService pauseService; private readonly IGameReadModel readModel; private readonly IGameStateService gameStateService; private readonly IGameTimerService timerService; private readonly TopPanelPresenter topPanelPresenter; private readonly IGameView view; private bool boardBuilt; public GamePresenter(IGameCommandDispatcher commandDispatcher, ICellViewFactory cellViewFactory, IGamePauseService pauseService, IGameReadModel readModel, IGameStateService gameStateService, IGameTimerService timerService, TopPanelPresenter topPanelPresenter, IGameView view = null) { this.commandDispatcher = commandDispatcher; this.cellViewFactory = cellViewFactory; this.pauseService = pauseService; this.readModel = readModel; this.gameStateService = gameStateService; this.timerService = timerService; this.topPanelPresenter = topPanelPresenter; this.view = view; } public void Initialize() { if (view != null) { view.RestartRequested += OnRestartRequested; view.GoToMenuRequested += OnGoToMenuRequested; view.PauseRequested += OnPauseRequested; view.ResumeRequested += OnResumeRequested; view.CellPressStarted += OnCellPressStarted; view.CellPressEnded += OnCellPressEnded; 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.CellPressStarted -= OnCellPressStarted; view.CellPressEnded -= OnCellPressEnded; view.CellOpenRequested -= OnCellOpenRequested; view.CellFlagRequested -= OnCellFlagRequested; gameStateService.StateChanged -= OnStateChanged; pauseService.PauseChanged -= OnPauseChanged; timerService.TimeChanged -= OnTimeChanged; } } private void OnRestartRequested() { commandDispatcher.Dispatch(new RestartCommand()); RebuildBoard(); topPanelPresenter.RefreshCounters(); } 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) { topPanelPresenter.SetCellPressActive(false); commandDispatcher.Dispatch(new OpenCellCommand(x, y)); RefreshBoard(); topPanelPresenter.RefreshCounters(); UpdateBoardInput(); } private void OnCellFlagRequested(int x, int y) { commandDispatcher.Dispatch(new ToggleFlagCommand(x, y)); RefreshBoard(); topPanelPresenter.RefreshCounters(); UpdateBoardInput(); } private void OnCellPressStarted() { topPanelPresenter.SetCellPressActive(true); } private void OnCellPressEnded() { topPanelPresenter.SetCellPressActive(false); } private void OnStateChanged(GameState state) { if (state == GameState.FieldSelection) { boardBuilt = false; view.HideGame(); view.HidePause(); view.HideResult(); return; } view.ShowGame(); if (state == GameState.Won || state == GameState.Lost) { view.HidePause(); view.ShowResult(state); } else { view.HideResult(); } if (!boardBuilt || state == GameState.Preparing) { RebuildBoard(); } else { RefreshBoard(); } UpdateBoardInput(); } private void OnPauseChanged(bool isPaused) { if (isPaused && gameStateService.Current == GameState.Playing) { 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, cellViewFactory, IsFinalState()); boardBuilt = true; topPanelPresenter.RefreshCounters(); UpdateBoardInput(); } private void RefreshBoard() { view.RefreshBoard(readModel.GetCells(), IsFinalState()); } private bool IsFinalState() { var state = gameStateService.Current; return state == GameState.Lost || state == GameState.Won; } private void UpdateBoardInput() { var state = gameStateService.Current; view.SetBoardInputEnabled(!pauseService.IsPaused && (state == GameState.Preparing || state == GameState.Playing)); } } }