namespace Marro.PacManUdon
{
    using UnityEngine;

    public enum PacManFruitType 
    {
        None = -1,
        Cherries = 0,
        Strawberry = 1,
        Peach = 2,
        Apple = 3,
        Grapes = 4,
        Galaxian = 5,
        Bell = 6,
        Key = 7
    }

    public enum PacManGameState 
    {
        AttractMode,
        AttractModeDemo,
        WaitForStart,
        InGame,
    }

    public enum PacManGhostFrozenState 
    {
        Frozen,
        FrozenIfNotCaught,
        NotFrozen
    }

    public enum PacManTimeSequence 
    {
        AttractScreenIntroduction,
        AttractScreenDemo,
        WaitForStart,
        WaitForStartTimeout,
        StartNewGame,
        BoardClear,
        StartNewLevel,
        GhostCaught,
        PacManCaught,
        RestartLevel,
        GameOver
    }

    public static class PacManConstants 
    {
        public static GameObject[] ComponentsToGameObjects(Component[] components, bool skipFirstComponent = false)
        {
            if (skipFirstComponent)
            {
                GameObject[] gameObjects = new GameObject[components.Length-1];
                for (int i = 0; i < components.Length-1; i++)
                {
                    gameObjects[i] = components[i+1].gameObject;
                }
                return gameObjects;
            }
            else
            {
                GameObject[] gameObjects = new GameObject[components.Length];
                for (int i = 0; i < components.Length; i++)
                {
                    gameObjects[i] = components[i].gameObject;
                }
                return gameObjects;
            }
            
        }

        public static float GetPowerPelletBlinkToggleInterval()
        {
            return 0.1666666666f;
        }

        public static PacManFruitType GetFruitTypeForLevel(int level)
        {
            PacManFruitType[] FruitTypePerLevel = new PacManFruitType[] 
            {
                PacManFruitType.Cherries, 
                PacManFruitType.Strawberry,
                PacManFruitType.Peach,
                PacManFruitType.Peach,
                PacManFruitType.Apple,
                PacManFruitType.Apple,
                PacManFruitType.Grapes,
                PacManFruitType.Grapes,
                PacManFruitType.Galaxian,
                PacManFruitType.Galaxian,
                PacManFruitType.Bell,
                PacManFruitType.Bell,
                PacManFruitType.Key
            };
            if (level-1 < 0) 
            {
                return PacManFruitType.None;
            }
            if (level-1 >= FruitTypePerLevel.Length) 
            {
                return FruitTypePerLevel[FruitTypePerLevel.Length-1];
            }
            return FruitTypePerLevel[level-1];
        }

        public static float GetGhostHomeSpeed()
        {
            return 3.5f;
        }

        public static float GetPacManDefaultSpeedForLevel(int level) 
        {
            if(level <=  1) return 7.576f;
            if(level <=  4) return 8.523f;
            if(level <= 20) return 9.470f;
                            return 8.523f;
        }

        public static float GetPacManPowerPelletSpeedForLevel(int level)
        {
            if(level <=  1) return 8.523f;
            if(level <=  4) return 8.996f;
                            return 9.470f;
        }

        public static float GetGhostDefaultSpeedForLevel(int level)
        {
            if(level <=  1) return 7.102f;
            if(level <=  4) return 8.049f;
                            return 8.996f;
        }

        public static float GetGhostTunnelSpeedForLevel(int level)
        {
            if(level <=  1) return 3.788f;
            if(level <=  4) return 4.261f;
                            return 4.735f;
        }

        public static float GetBlinkyElroy1SpeedForLevel(int level) 
        {
            if(level <=  1) return 7.576f;
            if(level <=  4) return 8.523f;
                            return 9.470f;
        }

        public static float GetBlinkyElroy2SpeedForLevel(int level) 
        {
            if(level <=  1) return 8.049f;
            if(level <=  4) return 8.996f;
                            return 9.943f;
        }

        public static float GetGhostScaredSpeedForLevel(int level) 
        {
            if(level <=  1) return 4.735f;
            if(level <=  4) return 5.208f;
                            return 5.682f;
        }

        public static int GetElroy1PelletsRemainingForLevel(int level) 
        {
            if(level <=  1) return  20;
            if(level <=  2) return  30;
            if(level <=  5) return  40;
            if(level <=  8) return  50;
            if(level <= 11) return  60;
            if(level <= 14) return  80;
            if(level <= 18) return 100;
                            return 120;
        }

        public static int GetElroy2PelletsRemainingForLevel(int level) 
        {
            if(level <=  1) return  10;
            if(level <=  2) return  15;
            if(level <=  5) return  20;
            if(level <=  8) return  25;
            if(level <= 11) return  30;
            if(level <= 14) return  40;
            if(level <= 18) return  50;
                            return  60;
        }

        public static float GetGhostHousePelletTimeoutLimitForLevel(int level)
        {
            if(level <= 4) return 4;
                        return 3;
        }

        public static int[] GetGhostHousePrivatePelletCounterLimitForLevel(int level)
        {
            if(level <= 1) return new int[] {  0,  0, 30, 60};
            if(level <= 2) return new int[] {  0,  0,  0, 50};
                        return new int[] {  0,  0,  0,  0};
        }

        public static float[] GetScatterPatternForLevel(int level) 
        {
            if(level <= 1) return new float[] { 7, 27, 34, 54, 59,   79,   84         };
            if(level <= 4) return new float[] { 7, 27, 34, 54, 59, 1092, 1092.0166667f};
                        return new float[] { 5, 25, 30, 50, 55, 1092, 1092.0166667f};
        }

        public static float GetScaredDurationForLevel(int level) 
        {
            float[] scaredDurationPerLevel =
            {
                6,
                5,
                4,
                3,
                2,
                5,
                2,
                2,
                1,
                5,
                2,
                1,
                1,
                3,
                1,
                1,
                0,
                1,
                0
            };
            if (level-1 < 0) 
            {
                return scaredDurationPerLevel[0];
            }
            if (level-1 >= scaredDurationPerLevel.Length) 
            {
                return scaredDurationPerLevel[scaredDurationPerLevel.Length-1];
            }
            return scaredDurationPerLevel[level-1];
        }

        public static float GetScaredNumberOfFlashesForLevel(int level) 
        {
            int[] scaredNumberOfFlashesPerLevel = new int[]
            {
                5,
                5,
                5,
                5,
                5,
                5,
                5,
                5,
                3,
                5,
                5,
                3,
                3,
                5,
                3,
                3,
                0,
                3,
                0
            };
            if (level-1 < 0) 
            {
                return scaredNumberOfFlashesPerLevel[0];
            }
            if (level-1 >= scaredNumberOfFlashesPerLevel.Length) 
            {
                return scaredNumberOfFlashesPerLevel[scaredNumberOfFlashesPerLevel.Length-1];
            }
            return scaredNumberOfFlashesPerLevel[level-1];
        }

        public static int FruitTypeToValue(PacManFruitType fruitType) { // I can't get casting from enum to int to work so this is a workaround
            switch (fruitType) 
            {
                default:
                case PacManFruitType.None:
                    return -1;
                case PacManFruitType.Cherries:
                    return 0;
                case PacManFruitType.Strawberry:
                    return 1;
                case PacManFruitType.Peach:
                    return 2;
                case PacManFruitType.Apple:
                    return 3;
                case PacManFruitType.Grapes:
                    return 4;
                case PacManFruitType.Galaxian:
                    return 5;
                case PacManFruitType.Bell:
                    return 6;
                case PacManFruitType.Key:
                    return 7;
            }
        }
    }
}