public static bool GetPreviousLevel(ref LevelPack levelPack, ref Level.LevelInfo levelInfo)
        {
            if (!levelPack.Levels.Contains(levelInfo))
            {
                throw new Exception($"Level [{levelInfo.ID}] is not part of Level Pack [{levelPack.ID}]");
            }

            var levelIndex = levelInfo.Index;

            if (levelIndex - 1 >= 0 && levelIndex < levelPack.TotalLevelCount)
            {
                // Previous Level in current pack
                var prevLevel = levelPack.Levels[levelIndex - 1];

                levelInfo = prevLevel;
                return(true);
            }

            if (levelIndex - 1 < 0)
            {
                // Previous Level in previous pack
                var prevPack = GetPreviousPack(levelPack);

                if (prevPack == null)
                {
                    return(false);                                  // No more levels
                }
                levelPack = prevPack;
                levelInfo = prevPack.Levels[prevPack.Levels.Count - 1];
                return(true);
            }

            return(false);
        }
        public static bool GetNextLevel(ref LevelPack levelPack, ref Level.LevelInfo levelInfo)
        {
            if (!levelPack.Levels.Contains(levelInfo))
            {
                throw new Exception($"Level [{levelInfo.ID}] is not part of Level Pack [{levelPack.ID}]");
            }

            var levelIndex = levelInfo.Index;

            if (levelIndex >= 0 && levelIndex + 1 < levelPack.TotalLevelCount)
            {
                // Next Level in current pack
                var nextLevel = levelPack.Levels[levelIndex + 1];

                levelInfo = nextLevel;
                return(true);
            }

            if (levelIndex + 1 >= levelPack.TotalLevelCount)
            {
                // Next Level in next pack
                var nextPack = GetNextPack(levelPack);

                if (nextPack == null)
                {
                    return(false);                                  // No more levels
                }
                levelPack = nextPack;
                levelInfo = nextPack.Levels[0];
                return(true);
            }

            return(false);
        }
 // TODO: Write testing around the following four methods
 public static bool HasNextLevel(LevelPack levelPack, Level.LevelInfo levelInfo, ref bool isUnlocked)
 {
     if (GetNextLevel(ref levelPack, ref levelInfo))
     {
         isUnlocked = levelInfo.Status != Level.LevelInfo.LevelInfoStatus.Locked;
         return(true);
     }
     return(false);
 }
        private static LevelPack GetNextPack(LevelPack currentLevelPack)
        {
            var packIndex = LevelPacks.IndexOf(currentLevelPack);

            if (packIndex < 0 || packIndex >= LevelPacks.Count - 1)
            {
                return(null);
            }

            var nextPack = LevelPacks[packIndex + 1];

            return(nextPack);
        }
        private static LevelPack GetPreviousPack(LevelPack currentLevelPack)
        {
            var packIndex = LevelPacks.IndexOf(currentLevelPack);

            if (packIndex - 1 < 0)
            {
                return(null);
            }

            var nextPack = LevelPacks[packIndex - 1];

            return(nextPack);
        }
        public static Level GetLevel(LevelPack levelPack, string levelID)
        {
            if (!levelPack.Levels.Contains(levelID))
            {
                throw new Exception($"No Level loaded with ID {levelID}");
            }

            var levelInfo       = levelPack.Levels[levelID];
            var serializedLevel = ContentManager.LoadContent(ContentTypes.Level, levelInfo.ID);
            var level           = Level.Parser.ParseLevel(serializedLevel);

            level.SetInfo(levelInfo);
            return(level);
        }
        private static void UnlockNextLevel(LevelPack levelPack, Level.LevelInfo level)
        {
            var levelIndex = level.Index;

            if (levelIndex >= 0 && levelIndex + 1 < levelPack.TotalLevelCount)
            {
                // Next Level in current pack
                var nextLevel = levelPack.Levels[levelIndex + 1];
                nextLevel.SetStatus(Level.LevelInfo.LevelInfoStatus.Unsolved);
                levelPack.SaveProgressForPack();
            }
            else if (levelIndex + 1 >= levelPack.TotalLevelCount)
            {
                // Next Level in next pack
                var nextPack = GetNextPack(levelPack);
                nextPack?.UnlockFirstLevel();
            }
        }
            public static LevelPack ParseLevelPack(string packID, string serializedLevelPack)
            {
                if (string.IsNullOrWhiteSpace(packID))
                {
                    throw new Exception($"Pack ID was not valid [{packID}]");
                }

                try
                {
                    // Parse the string as JSON
                    JObject levelJSON = JObject.Parse(serializedLevelPack);
                    if (levelJSON == null)
                    {
                        throw new InvalidSerializedLevelPackException("Level was not valid JSON");
                    }

                    var packName = levelJSON.Value <string>("PackName");
                    if (string.IsNullOrWhiteSpace(packName))
                    {
                        throw new InvalidSerializedLevelPackException($"Pack name was not valid [{packName}]");
                    }

                    var levelInfosJSON = (JArray)levelJSON["Levels"];
                    if (levelInfosJSON == null || levelInfosJSON.Count < 1)
                    {
                        throw new InvalidSerializedLevelPackException("Level pack did not contain any levels");
                    }

                    var levelInfos = new LevelList();
                    foreach (var levelInfoJSON in levelInfosJSON)
                    {
                        var levelInfo = ParseLevelInfo(levelInfoJSON, levelInfos.Count);
                        levelInfos.Add(levelInfo);
                    }

                    var levelPack = new LevelPack(packID, packName, levelInfos);
                    return(levelPack);
                }
                catch (Exception ex)
                {
                    throw new InvalidSerializedLevelPackException("Unable to parse level", ex);
                }
            }
        public static void SolveLevel(LevelPack levelPack, string levelID, bool isWithinMoves, bool hasCollectedSushi)
        {
            if (!levelPack.Levels.Contains(levelID))
            {
                throw new Exception($"No Level loaded with ID {levelID}");
            }

            // Get the pack's corresponding level info
            // Not using level.Info as the level's info might not be the same one as the pack
            var packLevelInfo = levelPack.Levels[levelID];

            // Mark the level as the correct level of solved
            bool isWithinMinMoves = packLevelInfo.IsSolvedWithinMinMoves || isWithinMoves;
            bool hasSushi         = packLevelInfo.IsSolvedWithSushi || hasCollectedSushi;

            if (isWithinMinMoves && hasSushi)
            {
                packLevelInfo.SetStatus(Level.LevelInfo.LevelInfoStatus.FullySolved);
            }
            else if (isWithinMinMoves && !hasSushi)
            {
                packLevelInfo.SetStatus(Level.LevelInfo.LevelInfoStatus.SolvedWithMinMoves);
            }
            else if (!isWithinMinMoves && hasSushi)
            {
                packLevelInfo.SetStatus(Level.LevelInfo.LevelInfoStatus.SolvedWithSushi);
            }
            else
            {
                packLevelInfo.SetStatus(Level.LevelInfo.LevelInfoStatus.Solved);
            }

            // Unlock next level and save the pack
            UnlockNextLevel(levelPack, packLevelInfo);
            levelPack.SaveProgressForPack();
        }
 public static bool HasPreviousLevel(LevelPack levelPack, Level.LevelInfo levelInfo) => GetPreviousLevel(ref levelPack, ref levelInfo);