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 IContainer _rootContainer { get; set; } 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 GameService(IContainer rootContainer = null) { _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, _game); 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(); 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); _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 = _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, _game); 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 bool FreePlayerSelection => _gh.FreePlayerSelection(); } }