using Math3;
using System;
using System.Collections.Generic;
using System.Drawing;

namespace Solitaire
{
    public class classPlayingCard
    {

        enuSuits _eSuit = enuSuits.Spade;
        public enuSuits eSuit { get { return _eSuit; } }

        enuRanks _eRank = enuRanks.Ace;
        public enuRanks eRank { get { return _eRank; } }

        Bitmap _bmp = null;
        public Bitmap bmp
        {
            get 
            {
                if (eSuit == enuSuits.Club && eRank == enuRanks.Ace)
                    ;
                return bolFaceUp ? _bmp : bmpFaceDown;
            }
        }

        static Bitmap _bmpFaceDown = null;
        public static Bitmap bmpFaceDown
        {
            get
            {
                if (_bmpFaceDown == null)
                {
                    _bmpFaceDown = new Bitmap(Properties.Resources.card_back);
                }
                return _bmpFaceDown;
            }
        }

        bool _bolFaceUp = false;
        public bool bolFaceUp
        {
            get { return _bolFaceUp; }
            set { _bolFaceUp = value; }
        }

        int intBankIndex = 0;
        public int BankIndex
        {
            get { return  intBankIndex; }
            set { intBankIndex = value; }
        }

        public classPlayingCard(enuRanks eRank, enuSuits eSuit)
        {
            _eRank = eRank;
            _eSuit = eSuit;
            classPlayingCard cMyRef = this;
            cCardMotion = new classCardMotion(ref cMyRef);
        }

        
        public static Size szCard = new Size();
        public static Size _szCard_base = new Size();
        public static Size szCard_base
        {
            get { return _szCard_base; }
        }
        public classCardMotion cCardMotion = null;
        public Point ptLocation = new Point();

        static List<classPlayingCard>[] _arrCardSuits = null;
        public static List<classPlayingCard>[] arrCardSuits
        {
            get
            {
                if (_arrCardSuits == null)
                {
                    _arrCardSuits = new List<classPlayingCard>[4];
                    for (int intSuitCounter =0; intSuitCounter < 4; intSuitCounter++)
                    {
                        _arrCardSuits[intSuitCounter] = new List<classPlayingCard>();
                    }
                }
                return _arrCardSuits;
            }
        }

        public static List<classPlayingCard> lstCardsInMotion =     new List<classPlayingCard>();
        public bool IAmMoving
        {
            get { return cCardMotion.IAmMoving; }
        }
            

        enuCardLocation _eCardLocation = enuCardLocation.Stock;
        public enuCardLocation eCardLocation
        {
            get { return _eCardLocation; }
            set { _eCardLocation = value; }
        }

        static List<classPlayingCard> lstDeckOfCards_Original = new List<classPlayingCard>();

        public static List<classPlayingCard> NewDeck()
        {
            List<classPlayingCard> lstRetVal = new List<classPlayingCard>();
            while(lstCardsInMotion.Count >0)
            {
                classPlayingCard cCardMoving = lstCardsInMotion[0];
                lstCardsInMotion.RemoveAt(0);
                cCardMoving.cCardMotion.Quit();
            }
            lstRetVal.AddRange(lstDeckOfCards_Original);

            return lstRetVal;
        }

        
        public static void BuildSet()
        {
            lstDeckOfCards_Original.Clear();
            Bitmap bmpMask = new Bitmap(Properties.Resources.Card_Mask);
            bmpMask.MakeTransparent(bmpMask.GetPixel(0, 0)); 
            _szCard_base = bmpMask.Size;

            bmpMask.MakeTransparent(bmpMask.GetPixel(bmpMask.Width / 2, bmpMask.Height / 2));
            string strDir = System.IO.Directory.GetCurrentDirectory() + "\\";
            int intNumSuits = Enum.GetNames(typeof( enuSuits)).Length;
            int intNumRanks = Enum. GetNames(typeof( enuRanks)).Length;

            for (int intSuitCounter = 0; intSuitCounter < intNumSuits; intSuitCounter ++)
            {
                for (int intRankCounter =0; intRankCounter < intNumRanks; intRankCounter++)
                {
                    enuRanks eRank = (enuRanks)intRankCounter;
                    enuSuits eSuit = (enuSuits)intSuitCounter;
                    classPlayingCard cPlayingCard = new classPlayingCard(eRank, eSuit);
                    arrCardSuits[(int)eSuit].Add(cPlayingCard);
                    string strFilename = strDir + eRank.ToString() + " of " + eSuit.ToString() + ".png";
                    if (System.IO.File.Exists(strFilename))
                    {
                        cPlayingCard._bmp = new Bitmap(strFilename);
                        cPlayingCard.bmp.MakeTransparent(cPlayingCard.bmp.GetPixel(0, 0));
                        lstDeckOfCards_Original.Add(cPlayingCard);
                    }
                    else
                    {
                        ;

                    }
                }
            }
        }

        public static void ShuffleDeck(ref List<classPlayingCard> lstCards)
        {
            if (lstCards.Count == 0) return;
            for (int intShuffleCounter =0; intShuffleCounter < 226; intShuffleCounter ++)
            {
                int intRndA = classRND.Get_Int(lstCards.Count);
                int intRndB = classRND.Get_Int(lstCards.Count);
                while (Math.Abs(intRndA - intRndB) < 2 
                    || intRndB ==0 || intRndB == 0 
                    || intRndA == lstCards.Count-1 || intRndB == lstCards.Count-1)
                {
                    intRndA = classRND.Get_Int(lstCards.Count);
                    intRndB = classRND.Get_Int(lstCards.Count);
                }

                int intRnd_Less = intRndA < intRndB ? intRndA : intRndB;
                int intRnd_Greater = intRndA > intRndB ? intRndA : intRndB;

                List<classPlayingCard> lstA = new List<classPlayingCard>();
                List<classPlayingCard> lstB = new List<classPlayingCard>();
                List<classPlayingCard> lstC = new List<classPlayingCard>();
                int intAStart = 0;
                int intARange = intRnd_Less;
                lstA.AddRange(lstCards.GetRange(intAStart, intARange));

                int intBStart = intRnd_Less;
                int intBRange = intRnd_Greater - intBStart;
                lstB.AddRange(lstCards.GetRange(intBStart, intBRange));

                int intCStart = intRnd_Greater;
                int intCRange = lstCards.Count - intCStart;
                lstC.AddRange(lstCards.GetRange(intCStart, intCRange));

                if (lstA.Count + lstB.Count + lstC.Count != lstCards.Count )
                {
                    ;
                }

                lstCards.Clear();
                // transform abc => cba 
                lstCards.AddRange(lstC);
                lstCards.AddRange(lstB);
                lstCards.AddRange(lstA);
            }
        }
        public static void SendCardsToFinalPosition()
        {
            while (lstCardsInMotion.Count > 0)
            {
                classPlayingCard cCard = lstCardsInMotion[0];
                lstCardsInMotion.RemoveAt(0);
                cCard.cCardMotion.GotoEndPosition();
            }
        }



        public class classCardMotion
        {
            public Point ptStart = new Point();
            public Point ptEnd = new Point();

            int _intTotalSteps = 15;
            int intTotalSteps
            {
                get { return _intTotalSteps; }
                set { _intTotalSteps = value; }
            }

            int intStepCounter = 0;
            classEventController.classEventTicket cEventTicket_MoveCard = null;
            classPlayingCard cCard = null;
            public classCardMotion(ref classPlayingCard cCard)
            {
                this.cCard = cCard;

                cEventTicket_MoveCard = formSolitaire.cEC.Ticket("MoveCard (" + cCard.eRank.ToString() + "-" + cCard.eSuit.ToString() + ")", 100, tmrMoveCard_Tick);
                cEventTicket_MoveCard.quit();
            }

            public void Quit()
            {
                cEventTicket_MoveCard.quit();
                lstCardsInMotion.Remove(cCard);

            }

            public void GotoEndPosition()
            {
                cCard.ptLocation = ptEnd;
                intStepCounter = intTotalSteps;
                cEventTicket_MoveCard.AutoRepeat = false;
                Quit();
            }

            void tmrMoveCard_Tick(object sender, EventArgs e)
            {
                intStepCounter++;
                int intDistanceX = ptEnd.X - ptStart.X;
                int intDistanceY = ptEnd.Y - ptStart.Y;
                float fltPCDistanceTravelled = (float)intStepCounter / (float)intTotalSteps;
                cCard.ptLocation = new Point((int)(ptStart.X + fltPCDistanceTravelled * intDistanceX),
                                             (int)(ptStart.Y + fltPCDistanceTravelled * intDistanceY));
                if (intStepCounter < intTotalSteps)
                    cEventTicket_MoveCard.AutoRepeat = true;
                else
                {
                    cEventTicket_MoveCard.AutoRepeat = false;
                    Quit();
                    lstCardsInMotion.Remove(cCard);
                    if (lstCardsInMotion.Count == 0)
                        pictureboxTable.instance.DrawTable();
                }
            }

            public bool IAmMoving { get { return cEventTicket_MoveCard.AutoRepeat; } }

            public void MoveTo(Point ptTarget) { MoveTo(ptTarget, intTotalSteps); }
            public void MoveTo(Point ptTarget, int intTotalSteps)
            {
                this.intTotalSteps = intTotalSteps;
                ptStart = cCard.ptLocation;
                ptEnd = ptTarget;
                intStepCounter = 0;
                lstCardsInMotion.Add(cCard);
                tmrMoveCard_Tick((object)this, new EventArgs());
                cEventTicket_MoveCard.AutoRepeat = true;
            }
        }

    }
}
