﻿using System;
using UnityEngine;

namespace BattleRoyale.Spells
{
	// ENUMERATORS //
	#region
    [System.Serializable]
    public enum SpellPrimaryType { Light = 0, Heavy = 1, Blast = 2, Barrier = 3 }
    
    [System.Serializable]
    public enum SpellSecondaryType { Cast = 0, Scatter = 1, Channel = 2 }
    
    [System.Serializable]
    public enum HoldFireBehavior { SingleCast = 0, Repeat = 1, Charge = 2 }

    [System.Serializable]
    public enum ChargingBehavior { None = 0, Unbounded = 1, FireAtMin = 2, FireAtMax = 3, HoldAtMin = 4, HoldAtMax = 5 }

    [System.Serializable]
    public enum SpellOverLimitBehavior { NoCast = 0, CacheOldestInstance = 1 }

    [System.Serializable]
    public enum StatScalingParam { NoScaling = 0, Rarity = 1, ManaCharged = 2 }
    
    [System.Serializable]
    public enum SpellTargettingBehavior { None = 0, Self = 1, ClosestForward = 2, ClosestRadial = 3, ClosestForwardUnobstructed = 4, ClosestRadialUnobstructed = 5 }
    
    [System.Serializable]
    public enum SpellScopeBehavior { PerTarget = 0, Global = 1 }
    
    [System.Serializable]
    public enum SpellCollisionBehavior { DestroyedOnHit = 0, PassesThrough = 1, BouncesOff = 2, HaltsAt = 3, SticksTo = 4, SnapsToCenter = 5 }

    [System.Serializable]
    public enum SpellForceDirection { CenterOut = 0, CenterIn = 1, GlobalUp = 2, LocalForward = 3, LocalBackward = 4 }
	#endregion
	
    /// <summary>
    /// Unified spell type based on primary and secondary characteristics.
    /// </summary>
    [System.Serializable]
    public struct SpellType
    {
        [SerializeField] public SpellPrimaryType Primary;
        [SerializeField] public SpellSecondaryType Secondary;

        public SpellType(SpellPrimaryType _primary, SpellSecondaryType _secondary)
        {
            this.Primary = _primary;
            this.Secondary = _secondary;
        }

        /// <summary>
        /// Returns a random Spell Type
        /// </summary>
        /// <returns></returns>
        public static SpellType Random()
        {
            // Get a random primary type
            SpellPrimaryType _randomPrimary = (SpellPrimaryType)UnityEngine.Random.Range(0, Enum.GetValues(typeof(SpellPrimaryType)).Length);

            // Get a random secondary type
            SpellSecondaryType _randomSecondary = (SpellSecondaryType)UnityEngine.Random.Range(0, Enum.GetValues(typeof(SpellSecondaryType)).Length);

            // Return the randomized type combination
            return new SpellType(_randomPrimary, _randomSecondary);
        }

        /// <summary>
        /// Returns true if the given integer/enumerated pair is a valid type combination
        /// </summary>
        /// <param name="_spellPrimaryType"></param>
        /// <param name="_spellSecondaryType"></param>
        /// <returns></returns>
        public static bool IsValidType(SpellType _spellType)
        {
            bool _isValid = Enum.IsDefined(typeof(SpellPrimaryType), _spellType.Primary) && Enum.IsDefined(typeof(SpellSecondaryType), _spellType.Secondary);

            if (!_isValid)
                Debug.LogError("Type " + _spellType.ToString() + " does not exist. This likely occurs during network play between clients with different versions of the game.");

            return _isValid;
        }
        public static bool IsValidType(SpellPrimaryType _spellPrimaryType, SpellSecondaryType _spellSecondaryType)
        {
            bool _isValid = Enum.IsDefined(typeof(SpellPrimaryType), _spellPrimaryType) && Enum.IsDefined(typeof(SpellSecondaryType), _spellSecondaryType);

            if (!_isValid)
                Debug.LogError("Type " + new SpellType(_spellPrimaryType, _spellSecondaryType).ToString() + " does not exist. This likely occurs during network play between clients with different versions of the game.");

            return _isValid;
        }
        public static bool IsValidType(int _spellPrimaryType, int _spellSecondaryType)
        {
            bool _isValid = Enum.IsDefined(typeof(SpellPrimaryType), _spellPrimaryType) && Enum.IsDefined(typeof(SpellSecondaryType), _spellSecondaryType);

            if (!_isValid)
                Debug.LogError("Type " + new SpellType((SpellPrimaryType)_spellPrimaryType, (SpellSecondaryType)_spellSecondaryType).ToString() + " does not exist. This likely occurs during network play between clients with different versions of the game.");

            return _isValid;
        }

        public static bool operator ==(SpellType s1, SpellType s2)
        {
            return (s1.Primary == s2.Primary && s1.Secondary == s2.Secondary);
        }

        public static bool operator !=(SpellType s1, SpellType s2)
        {
            return (s1.Primary != s2.Primary || s1.Secondary != s2.Secondary);
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        private bool Equals(SpellType _spellType)
        {
            return (this.Primary == _spellType.Primary && this.Secondary == _spellType.Secondary);
        }

        public override int GetHashCode()
        {
            return Primary.GetHashCode() + Secondary.GetHashCode();
        }

        public override string ToString()
        {
            return Primary.ToString() + " " + Secondary.ToString();
        }
    }
}
