public async Task Save(string path, BlackHoleGameTable gameTable)
        {
            try
            {
                using (StreamWriter writer = new StreamWriter(path))
                {
                    // save the game status and details
                    writer.Write(gameTable.TableSize + " ");
                    await writer.WriteAsync(gameTable.GameStatus + " ");
                    await writer.WriteAsync(gameTable.CoordinatesOfChosenField.Item1 + " " + gameTable.CoordinatesOfChosenField.Item2 + " ");
                    await writer.WriteAsync(gameTable.IsGameActive + " ");
                    await writer.WriteAsync(gameTable.PlayerAScore + " ");
                    await writer.WriteAsync(gameTable.PlayerBScore + "");

                    // save the game table values
                    await writer.WriteLineAsync();
                    for (Int32 row = 0; row < gameTable.TableSize; ++row)
                    {
                        for (Int32 column = 0; column < gameTable.TableSize; ++column)
                        {
                            await writer.WriteAsync(gameTable[row, column] + " ");
                        }
                        await writer.WriteLineAsync();
                    }
                }
            }
            catch
            {
                throw new BlackHoleGameDataException("Save file path is wrong.");
            }
        }
        public async Task Save(object descriptor, BlackHoleGameTable gameTable)
        {
            try
            {
                StringBuilder builder = new StringBuilder();
                // save the game status and details
                builder.Append(gameTable.TableSize + " ");
                builder.Append(gameTable.GameStatus + " ");
                builder.Append(gameTable.CoordinatesOfChosenField.Item1 + " " + gameTable.CoordinatesOfChosenField.Item2 + " ");
                builder.Append(gameTable.IsGameActive + " ");
                builder.Append(gameTable.PlayerAScore + " ");
                builder.Append(gameTable.PlayerBScore + " ");

                // save the game table values
                builder.AppendLine();
                for (Int32 row = 0; row < gameTable.TableSize; ++row)
                {
                    for (Int32 column = 0; column < gameTable.TableSize; ++column)
                    {
                        builder.Append(gameTable[row, column] + " ");
                    }
                    builder.AppendLine();
                }

                StorageFile file = descriptor as StorageFile;
                await FileIO.WriteTextAsync(file, builder.ToString());
            }
            catch
            {
                throw new BlackHoleGameDataException("Save file path is wrong.");
            }
        }
        public async Task<BlackHoleGameTable> Load(object descriptor)
        {
            try
            {
                StorageFile file = descriptor as StorageFile;
                String[] fileContent = (await FileIO.ReadTextAsync(file)).Split(' ');
                
                Int32 tableSize = Int32.Parse(fileContent[0]);

                BlackHoleGameTable gameTable = new BlackHoleGameTable(tableSize);

                // loading game status and table details to the new returnable table
                gameTable.GameStatus = (GameStatus)Enum.Parse(typeof(GameStatus), fileContent[1]);
                gameTable.CoordinatesOfChosenField = Tuple.Create(Int32.Parse(fileContent[2]), Int32.Parse(fileContent[3]));
                gameTable.IsGameActive = (fileContent[4] == "True") ? true : false;
                gameTable.PlayerAScore = Int32.Parse(fileContent[5]);
                gameTable.PlayerBScore = Int32.Parse(fileContent[6]);
                
                for (Int32 row = 0; row < tableSize; ++row)
                {
                    for (Int32 column = 0; column < tableSize; ++column)
                    {
                        gameTable[row, column] = (FieldType)Enum.Parse(typeof(FieldType), fileContent[7 + (row * tableSize) + column]); ;
                    }
                }

                return gameTable;
            }
            catch
            {
                throw new BlackHoleGameDataException("Load file path is wrong or the file is corrupted.");
            }
        }
        /// <summary>
        /// Start a new game.
        /// </summary>
        /// <param name="tableSize">The size of the game table.</param>
        public void NewGame(Int32 tableSize)
        {
            // generate new table
            gameTable = new BlackHoleGameTable(tableSize);

            for (Int32 row = 0; row < tableSize; ++row)
                for (Int32 column = 0; column < tableSize; ++column)
                {
                    gameTable[row, column] = FieldType.Empty;
                    OnFieldChanged(row, column, FieldType.Empty);

                    // blackhole
                    if (row == column && row == (tableSize / 2))
                    {
                        gameTable[row, column] = FieldType.BlackHole;
                        OnFieldChanged(row, column, FieldType.BlackHole);
                    }

                    // player A fields
                    if ((row == column || row + column == tableSize - 1) && row < tableSize / 2)
                    {
                        gameTable[row, column] = FieldType.PlayerA;
                        OnFieldChanged(row, column, FieldType.PlayerA);
                    }

                    // player B fields
                    if ((row == column || row + column == tableSize - 1) && row > tableSize / 2)
                    {
                        gameTable[row, column] = FieldType.PlayerB;
                        OnFieldChanged(row, column, FieldType.PlayerB);
                    }
                }

            gameTable.IsGameActive = true;
            OnScoresChanged(gameTable.PlayerAScore, gameTable.PlayerBScore);
            OnTableStatusChanged(gameTable.GameStatus);
        }
        public async Task<BlackHoleGameTable> Load(string path)
        {
            try
            {
                using (StreamReader reader = new StreamReader(path))
                {
                    String line = await reader.ReadLineAsync();
                    String[] gameState = line.Split(' ');
                    Int32 tableSize = Int32.Parse(gameState[0]);

                    BlackHoleGameTable gameTable = new BlackHoleGameTable(tableSize);

                    // loading game status and table details to the new returnable table
                    gameTable.GameStatus = (GameStatus)Enum.Parse(typeof(GameStatus), gameState[1]);
                    gameTable.CoordinatesOfChosenField = Tuple.Create(Int32.Parse(gameState[2]), Int32.Parse(gameState[3]));
                    gameTable.IsGameActive = (gameState[4] == "True") ? true : false;
                    gameTable.PlayerAScore = Int32.Parse(gameState[5]);
                    gameTable.PlayerBScore = Int32.Parse(gameState[6]);

                    for (Int32 row = 0; row < tableSize; ++row)
                    {
                        line = await reader.ReadLineAsync();
                        String[] fieldValues = line.Split(' ');
                        for (Int32 column = 0; column < tableSize; ++column)
                        {
                            gameTable[row, column] = (FieldType)Enum.Parse(typeof(FieldType), fieldValues[column]); ;
                        }
                    }

                    return gameTable;
                }
            }
            catch
            {
                throw new BlackHoleGameDataException("Load file path is wrong or the file is corrupted.");
            }
        }
        /// <summary>
        /// Game loading.
        /// </summary>
        /// <param name="path">File path.</param>
        public async Task LoadGame(String path)
        {
            if (dataAccess == null)
                throw new InvalidOperationException("Data access needed.");

            gameTable = await dataAccess.Load(path);

            // looking for errors in loaded gameTable
            CheckLoadedGameTable();
            
            // assuming gameTable is correct
            OnTableSizeChanged(gameTable.TableSize);

            // send signals to the view about the changes
            OnTableStatusChanged(gameTable.GameStatus);
            OnScoresChanged(gameTable.PlayerAScore, gameTable.PlayerBScore);
            for (Int32 row = 0; row < gameTable.TableSize; ++row)
            {
                for (Int32 column = 0; column < gameTable.TableSize; ++column)
                {
                    OnFieldChanged(row, column, gameTable[row, column]);
                }
            }
            OnLoadGameFinished();
        }