﻿using System.Collections.Generic;
using UnityEngine;
using System;


namespace BattleRoyale.Spells
{
    [CreateAssetMenu(fileName = "Data", menuName = "BattleRoyale/Spell Collection", order = 1)]
    [System.Serializable]
    public class SpellCollection : ScriptableObject
    {
        // Spell Fields //
        /// <summary>
        /// Light Spell Subtype
        /// </summary>
        public Spell LightCast, LightScatter, LightChannel;
        /// <summary>
        /// Heavy Spell Subtype
        /// </summary>
        public Spell HeavyCast, HeavyScatter, HeavyChannel;
        /// <summary>
        /// Blast Spell Subtype
        /// </summary>
        public Spell BlastCast, BlastScatter, BlastChannel;
        /// <summary>
        /// Barrier Spell Subtype
        /// </summary>
        public Spell BarrierCast, BarrierScatter, BarrierChannel;

        public GameObject DestructionEffect;
        public GameObject SealPrefab;

        // Public Methods //
        /// <summary>
        /// Returns true if the collection has at least one valid spell
        /// </summary>
        /// <returns></returns>
        public bool ContainsSpells()
        {
            // Loop through each type and check if that type exists in the collection
            for (int p = 0; p < Enum.GetValues(typeof(SpellPrimaryType)).Length; p++)
                for (int s = 0; s < Enum.GetValues(typeof(SpellSecondaryType)).Length; s++)
                    if (ContainsSpellOfType(new SpellType((SpellPrimaryType)p, (SpellSecondaryType)s)))
                        // If so, return true
                        return true;

            // Otherwise, return false
            return false;
        }

        /// <summary>
        /// Returns true if the collection contains a spell of the given type
        /// </summary>
        /// <param name="_type"></param>
        /// <returns></returns>
        public bool ContainsSpellOfType(SpellType _type)
        {
            // Get a preset from the type combination.
            switch (_type.Primary)
            {
                case (SpellPrimaryType.Light):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return LightCast;
                        case (SpellSecondaryType.Scatter):
                            return LightScatter;
                        case (SpellSecondaryType.Channel):
                            return LightChannel;
                    }
                    break;
                case (SpellPrimaryType.Heavy):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return HeavyCast;
                        case (SpellSecondaryType.Scatter):
                            return HeavyScatter;
                        case (SpellSecondaryType.Channel):
                            return HeavyChannel;
                    }
                    break;
                case (SpellPrimaryType.Blast):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return BlastCast;
                        case (SpellSecondaryType.Scatter):
                            return BlastScatter;
                        case (SpellSecondaryType.Channel):
                            return BlastChannel;
                    }
                    break;
                case (SpellPrimaryType.Barrier):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return BarrierCast;
                        case (SpellSecondaryType.Scatter):
                            return BarrierScatter;
                        case (SpellSecondaryType.Channel):
                            return BarrierChannel;
                    }
                    break;
            }

            // For safety, in case we receive an unexpected type, return false 
            return false;
        }

        /// <summary>
        /// Returns a spell from the collection of the given type
        /// </summary>
        /// <param name="_type"></param>
        /// <returns></returns>
        public Spell GetSpellOfType(SpellType _type)
        {
            // Get a preset from the type combination.
            switch (_type.Primary)
            {
                case (SpellPrimaryType.Light):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return LightCast;
                        case (SpellSecondaryType.Scatter):
                            return LightScatter;
                        case (SpellSecondaryType.Channel):
                            return LightChannel;
                    }
                    break;
                case (SpellPrimaryType.Heavy):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return HeavyCast;
                        case (SpellSecondaryType.Scatter):
                            return HeavyScatter;
                        case (SpellSecondaryType.Channel):
                            return HeavyChannel;
                    }
                    break;
                case (SpellPrimaryType.Blast):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return BlastCast;
                        case (SpellSecondaryType.Scatter):
                            return BlastScatter;
                        case (SpellSecondaryType.Channel):
                            return BlastChannel;
                    }
                    break;
                case (SpellPrimaryType.Barrier):
                    switch (_type.Secondary)
                    {
                        case (SpellSecondaryType.Cast):
                            return BarrierCast;
                        case (SpellSecondaryType.Scatter):
                            return BarrierScatter;
                        case (SpellSecondaryType.Channel):
                            return BarrierChannel;
                    }
                    break;
            }

            // For safety, in case we receive an unexpected type, return null 
            return null;
        }

        /// <summary>
        /// Returns a random spell from the collection
        /// </summary>
        /// <returns></returns>
        public Spell GetRandomSpell()
        {
            // Create a temporary list for spells
            List<Spell> _availableSpells = new List<Spell>();

            // Loop through the spell types and return add any non-null spells
            for (int p = 0; p < Enum.GetValues(typeof(SpellPrimaryType)).Length; p++)
                for (int s = 0; s < Enum.GetValues(typeof(SpellSecondaryType)).Length; s++)
                    if (ContainsSpellOfType(new SpellType((SpellPrimaryType)p, (SpellSecondaryType)s)))
                        _availableSpells.Add(GetSpellOfType(new SpellType((SpellPrimaryType)p, (SpellSecondaryType)s)));

            // Return a random spell from that list
            return _availableSpells[UnityEngine.Random.Range(0, _availableSpells.Count)];
        }

        /// <summary>
        /// Returns a random spell type that can be found in the collection
        /// </summary>
        /// <returns></returns>
        public SpellType GetRandomValidType()
        {
            // Create a temporary list for spell types
            List<SpellType> _availableSpellTypes = new List<SpellType>();

            // Loop through the spell types and return add any that can be found in the collection
            for (int p = 0; p < Enum.GetValues(typeof(SpellPrimaryType)).Length; p++)
                for (int s = 0; s < Enum.GetValues(typeof(SpellSecondaryType)).Length; s++)
                    if (ContainsSpellOfType(new SpellType((SpellPrimaryType)p, (SpellSecondaryType)s)))
                        _availableSpellTypes.Add(new SpellType((SpellPrimaryType)p, (SpellSecondaryType)s));

            // Return a random spell from that list
            return _availableSpellTypes[UnityEngine.Random.Range(0, _availableSpellTypes.Count)];

        }
    }
}