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

namespace pdinklag.CPW.Common
{
    /// <summary>
    /// Describes a wrestler's moveset.
    /// </summary>
    [Serializable]
    public class Moveset
    {
        private class EntriesList : IEnumerable<IMovesetEntry>
        {
            private readonly Moveset _moveset;

            public EntriesList(Moveset moveset)
            {
                _moveset = moveset;
            }

            public IEnumerator<IMovesetEntry> GetEnumerator() => _moveset.EnumerateEntries();
            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
        }

        [Header("Strikes")]
        [Tooltip("The wrestler's strikes.")]
        public DirectionChoiceMovesetEntry StandingStrikes;

        [Tooltip("The wrestler's heavy strikes.")]
        public DirectionChoiceMovesetEntry StandingHeavyStrikes;

        [Tooltip("The wrestler's strikes against a grounded opponent.")]
        public DirectionChoiceMovesetEntry GroundStrikes;

        [Tooltip("The wrestler's strikes from a crouching position.")]
        public ButtonInteractionMovesetEntry CrouchStrikes;

        [Tooltip("The wrestler's strikes from the apron towards inside the ring.")]
        public ButtonInteractionMovesetEntry ApronInsideStrikes;

        [Tooltip("The wrestler's strikes from the apron towards the left.")]
        public ButtonInteractionMovesetEntry ApronLeftStrikes;

        [Tooltip("The wrestler's strikes from the apron towards the right.")]
        public ButtonInteractionMovesetEntry ApronRightStrikes;

        [Header("Grapple")]
        [Tooltip("The wrestler's moves available when locking up.")]
        public DirectionChoiceMovesetEntry LockUpMoves;

        [Tooltip("The wrestler's front grapple moves.")]
        public DirectionChoiceMovesetEntry FrontGrappleMoves;

        [Tooltip("The wrestler's quick front grapple moves.")]
        public DirectionChoiceMovesetEntry QuickFrontGrappleMoves;

        [Tooltip("The wrestler's back grapple moves.")]
        public DirectionChoiceMovesetEntry BackGrappleMoves;

        [Header("Ground")]
        [Tooltip("The wrestler's moves available when standing at the head of an opponent laying supine.")]
        public SingletonMovesetEntry GroundSupineHeadMove;

        [Tooltip("The wrestler's moves available when standing at the feet of an opponent laying supine.")]
        public SingletonMovesetEntry GroundSupineFeetMove;

        [Tooltip("The wrestler's moves available when standing at the head of an opponent laying prone.")]
        public SingletonMovesetEntry GroundProneHeadMove;

        [Tooltip("The wrestler's moves available when standing at the feet of an opponent laying prone.")]
        public SingletonMovesetEntry GroundProneFeetMove;

        [Header("Running")]
        [Tooltip("The wrestler's running attacks.")]
        public TwoAlternativesMovesetEntry RunningAttacks;

        [Tooltip("The wrestler's running ground attacks.")]
        public TwoAlternativesMovesetEntry RunningGroundAttacks;

        [Header("Corner")]
        [Tooltip("The wrestler's moves against opponents in a corner.")]
        public DirectionChoiceMovesetEntry CornerMoves;

        [Header("Flying")]
        [Tooltip("The wrestler's flying attacks.")]
        public AnyDirectionMovesetEntry FlyingAttacks;

        [Tooltip("The wrestler's flying attacks against grounded opponents.")]
        public AnyDirectionMovesetEntry FlyingGroundAttacks;

        [Tooltip("The wrestler's backward flying attacks.")]
        public AnyDirectionMovesetEntry FlyingBackwardAttacks;

        [Header("Counters")]
        [Tooltip("The wrestler's back grapple counter.")]
        public SingletonMovesetEntry BackGrappleCounter;

        [Tooltip("The wrestler's moves available when holding the opponent's leg countering a kick.")]
        public DirectionChoiceMovesetEntry HoldLegMoves;

        [Header("Taunts")]
        [Tooltip("The wrestler's standing taunts.")]
        public StrictDirectionChoiceMovesetEntry StandingTaunts;

        public Moveset()
        {
        }

        public Moveset(Moveset other)
        {
            StandingStrikes = new(other.StandingStrikes);
            StandingHeavyStrikes = new(other.StandingHeavyStrikes);
            GroundStrikes = new(other.GroundStrikes);
            CrouchStrikes = new(other.CrouchStrikes);
            ApronInsideStrikes = new(other.ApronInsideStrikes);
            ApronLeftStrikes = new(other.ApronLeftStrikes);
            ApronRightStrikes = new(other.ApronRightStrikes);

            LockUpMoves = new(other.LockUpMoves);
            FrontGrappleMoves = new(other.FrontGrappleMoves);
            QuickFrontGrappleMoves = new(other.QuickFrontGrappleMoves);
            BackGrappleMoves = new(other.BackGrappleMoves);

            GroundSupineHeadMove = new(other.GroundSupineHeadMove);
            GroundSupineFeetMove = new(other.GroundSupineFeetMove);
            GroundProneHeadMove = new(other.GroundProneHeadMove);
            GroundProneFeetMove = new(other.GroundProneFeetMove);

            RunningAttacks = new(other.RunningAttacks);
            RunningGroundAttacks = new(other.RunningGroundAttacks);

            CornerMoves = new(other.CornerMoves);

            FlyingAttacks = new(other.FlyingAttacks);
            FlyingGroundAttacks = new(other.FlyingGroundAttacks);
            FlyingBackwardAttacks = new(other.FlyingBackwardAttacks);

            BackGrappleCounter = new(other.BackGrappleCounter);
            HoldLegMoves = new(other.HoldLegMoves);

            StandingTaunts = new(other.StandingTaunts);
        }

        private IEnumerator<IMovesetEntry> EnumerateEntries()
        {
            yield return StandingStrikes;
            yield return StandingHeavyStrikes;
            yield return GroundStrikes;
            yield return CrouchStrikes;
            yield return ApronInsideStrikes;
            yield return ApronLeftStrikes;
            yield return ApronRightStrikes;
            yield return LockUpMoves;
            yield return FrontGrappleMoves;
            yield return QuickFrontGrappleMoves;
            yield return BackGrappleMoves;
            yield return GroundSupineHeadMove;
            yield return GroundSupineFeetMove;
            yield return GroundProneHeadMove;
            yield return GroundProneFeetMove;
            yield return RunningAttacks;
            yield return RunningGroundAttacks;
            yield return CornerMoves;
            yield return FlyingAttacks;
            yield return FlyingGroundAttacks;
            yield return FlyingBackwardAttacks;
            yield return BackGrappleCounter;
            yield return HoldLegMoves;
            yield return StandingTaunts;
        }

        public IEnumerable<IMovesetEntry> Entries() => new EntriesList(this);
    }
}
