using GameHandler.Extensions; using GameModel; using GameModel.Exceptions; using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using GameHandler.GameHandler; using GameHandler.Parser; using GameModel.Contract; using GameModel.DeathGame; using GameModel.Contracts; using System.Data; using Autofac.Core; using Autofac; using static System.Formats.Asn1.AsnWriter; namespace GameHandler { public class GameService { private readonly IContainer? _rootContainer; private bool _isStarted = false; private ILifetimeScope? _scope; private IGameHandler? _gh; private ThrowHandler? _th; private ExpenseHandler? _eh; private GameStateHandler? _gameStateHandler; private Game? _game; public GameState? GameModel { get => _gameStateHandler?.GameState; } public bool FreePlayerSelection => _gh != null && _gh.FreePlayerSelection(); public GameService(IContainer? rootContainer = null) { this._rootContainer = rootContainer; } public string ThrowModeName { get { if (_gameStateHandler?.GameState != null) { return _gameStateHandler.GameState.ThrowState.BoardState.ThrowMode == ThrowMode.Decrease ? "Abräumen" : "Volle"; } return string.Empty; } } static int[] defaultPlayerIds => new[] {1,2,3,4}; public async Task Start(string gameName = FreeGameHandler.GAMENAME_FREETRAINING) { return await Start(defaultPlayerIds, new DeathGameSettings(6), gameName); } public async Task Start(int[] playerIds, IGameSettings gameSettings, string gameName = FreeGameHandler.GAMENAME_FREETRAINING) { if (_isStarted) { throw new InvalidGameStateExcpetion("Game already started"); } _isStarted = true; InitGameServiceBehaviour(gameName); var state = await InitGameState(playerIds, gameSettings, gameName); await _gameStateHandler.Add(state); await _gameStateHandler.Add(ExpenseModel.Create()); return state; } private async Task InitGameState(int[] playerIds, IGameSettings gameSettings, string gameName) { var gm = _gh.InitGameModel(playerIds, gameSettings); var throwState = ThrowState.Create(_gh.ThrowMode(), _gh.ThrowsPerRount()); _game = await _gameStateHandler.CreateNewGame(gameName); return GameState.Create(_game.Id, gameName, throwState, _gh.GetCurrentPlayerId(gm), gm); } private void InitGameServiceBehaviour(string gameName) { _scope = _rootContainer?.BeginLifetimeScope(); _gh = this.GetGameHandler(gameName); _gh.GameExpenseOccured += _gh_GameExpenseOccured; _th = new ThrowHandler(); _eh = new ExpenseHandler(_scope.Resolve()); _gameStateHandler = new GameStateHandler(_scope.Resolve(), _scope.Resolve()); } private void _gh_GameExpenseOccured(object? sender, EventArgs e) { var expenseModel = _eh.HandleGameExenseEventArgs(e as GameExenseEventArgs, _gameStateHandler.ExpenseModel).Result; _gameStateHandler.Add(expenseModel); //_lastState = _lastState with { ExpenseModel = expenseModel }; } public async Task HandleThrow(PinThrow pinThrow) { if (!_isStarted) { throw new InvalidGameStateExcpetion("Game not started"); } var lastGameState = _gameStateHandler.GameState; var boardStateBeforeUpdate = lastGameState.ThrowState.BoardState; pinThrow = AutoCompletePlayerId(pinThrow); var throwStateAfterUpdate = _th.Update(lastGameState.ThrowState, pinThrow); var gameModel = _gh.Update(pinThrow, lastGameState.GameModel, boardStateBeforeUpdate, throwStateAfterUpdate); var expenseModel = await _eh.CheckThrow(throwStateAfterUpdate.BoardState, pinThrow, gameModel.PlayerIds, _gameStateHandler.ExpenseModel); var newGameState = lastGameState with { ThrowState = throwStateAfterUpdate, GameModel = gameModel, NextPlayerId = _gh.GetCurrentPlayerId(gameModel) }; await _gameStateHandler.Add(expenseModel); await _gameStateHandler.Add(newGameState); return newGameState; } private PinThrow AutoCompletePlayerId(PinThrow pinThrow) { if (_gh.FreePlayerSelection() && pinThrow.PlayerId == 0) { throw new InvalidPinThrowException("PlayerId connot be 0"); } if (_gh.FreePlayerSelection()) { return pinThrow; } return pinThrow with { PlayerId = _gh.GetCurrentPlayerId(_gameStateHandler.GameState.GameModel) }; } public void Stop() { if (!_isStarted) { throw new InvalidGameStateExcpetion("Game not started"); } _isStarted = false; _scope?.Dispose(); } public ThrowCommandData ParseThrowData(string stringData) { return ThrowCommandParser.Parse(stringData, _gh.FreePlayerSelection(), 0); } public async Task Load(Guid gameId) { Game? game = null; using (var scope = _rootContainer?.BeginLifetimeScope()) { var gs = new GameStateHandler(scope.Resolve(), scope.Resolve()); game = await gs.LoadGame(gameId); } if (game == null) { return null; } _game = game; InitGameServiceBehaviour(game.GameName); var res = await _gameStateHandler.LoadState(game.Id); _isStarted = res != null; return res; } public GameState Undo() { if (_game == null) { throw new InvalidGameStateExcpetion("Game not initialized"); } if (!_isStarted) { throw new InvalidGameStateExcpetion("Game not started"); } var previousState = _gameStateHandler.Undo(); if (previousState != null) { return previousState; } return _gameStateHandler?.GameState; } public GameState Redo() { if (_game == null) { throw new InvalidGameStateExcpetion("Game not initialized"); } if (!_isStarted) { throw new InvalidGameStateExcpetion("Game not started"); } return _gameStateHandler.Redo(); } } }