//  
//  ListPlayers.cs
//  
//  Author:
//       Robert BRACCAGNI alias Gai-Luron <lfsgailuron@free.fr>
// 
//  Copyright (c) 2010 Gai-Luron
// 
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
// 
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
// 
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.


using System;
using System.Text;
using System.Collections;



namespace LFSLapper
{


    public class listPlayers
    {
        public Hashtable playersUCID = new Hashtable();
        public Hashtable playersUserName = new Hashtable();
        public Hashtable playersPLID = new Hashtable();
        private InSim.Connect IC;
        private bool onHost = false;
        private GLDebug.Debug myDebug;
        private lang lfsLang;
		private bool blinkVisible = true;
        public listPlayers( GLDebug.Debug pmyDebug, InSim.Connect pIC, lang plfsLang )
        {
            this.myDebug = pmyDebug;
            this.IC = pIC;
            this.lfsLang = plfsLang;
        }
        public void newPlayer(LapperThreads.PubStatUser pubStatUser,Configurator.lexConfigurator newCfg, int UCID, string username, string nickname, int Flags, string Product )
        {
            playersUCID[UCID] = new infoPlayer( pubStatUser, myDebug, IC, UCID,username,nickname, Product );
            playersUserName[username.ToLower()] = playersUCID[UCID];
            if (username == "" && Flags == 0 ) 
                this.onHost = true;
        }
        public void removePlayer(Configurator.lexConfigurator newCfg, int UCID)
        {
            if ((playersUCID[UCID] as infoPlayer).PLID != -1)
                playersPLID.Remove((playersUCID[UCID] as infoPlayer).PLID);
            playersUserName.Remove((playersUCID[UCID] as infoPlayer).userName);
            playersUCID.Remove(UCID);


        }
        public infoPlayer getPlayerByUCID(int UCID)
        {
            if (playersUCID.ContainsKey(UCID))
                return (infoPlayer)playersUCID[UCID];
            else
                return null;
        }
        public infoPlayer getPlayerByUserName(string UN)
        {
            if (playersUserName.ContainsKey(UN.ToLower()))
                return (infoPlayer)playersUserName[UN.ToLower()];
            else
                return null;
        }
        public infoPlayer getPlayerByPLID(int PLID)
        {
            if (playersPLID.ContainsKey(PLID))
                return (infoPlayer)playersPLID[PLID];
            else
                return null;
        }
        public infoPlayer getPlayerByFinishedPLID(int PLID)
        {
            if (PLID == 0)
                return null;
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                if (currInfoPlayer.finishedPLID == PLID)
                    return currInfoPlayer;
            }
            return null;
        }
        public int countPlayer()
        {
            if( onHost )
                return playersUCID.Count - 1;
            else
                return playersUCID.Count;

            }
        public void removeIndexPLID(int PLID)
        {
            (playersPLID[PLID] as infoPlayer).PLID = -1;
            playersPLID.Remove(PLID);
        }

        public void majIndexPLID(int UCID, int PLID )
        {
            playersPLID[PLID] = playersUCID[UCID];
            (playersUCID[UCID] as infoPlayer).PLID = PLID;
        }
        public void changeTrack(string newTrack, LFSDbs.gripDbs gripSqlDbs, LFSDbs.driftDbs driftSqlDbs)
        {
// Retrouver les infos de tous les joueurs
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
//                Console.WriteLine("Retreive : " + currInfoPlayer.userName + " Car : " + currInfoPlayer.CName + " Track : " + newTrack);
                currInfoPlayer.clearSessionInfo();

                gripSqlDbs.retreiveRow(currInfoPlayer, newTrack);
                driftSqlDbs.retreiveRow(currInfoPlayer, newTrack);

            }
        }

        public void updateGap( int PLID, int split, Configurator.lexConfigurator newCfg,bool modifyOnlyPos ){
            infoPlayer currInfoPlayer = this.getPlayerByPLID(PLID);
            // I'am first

            if (currInfoPlayer == null)
                return;

            string[] par = new string[2];
            par[0] = currInfoPlayer.userName;
            if (split != -1)
            {
                par[1] = (split + 1).ToString();
            }
            else
                par[1] = split.ToString();


                if (currInfoPlayer.currPos == 0)
                {
                    currInfoPlayer.UNameBefore = "";
                    currInfoPlayer.gapBefore = "";
                    currInfoPlayer.UNameBehind = "";
                    currInfoPlayer.gapBehind = "";
                    return;
                }
            if (currInfoPlayer.currPos == 1)
            {
                currInfoPlayer.UNameBefore = "";
                currInfoPlayer.gapBefore = "";
                newCfg.executeFunction("OnNewGapPlayerBefore", currInfoPlayer,par);
                return;
            }
            bool flagLast = true;
            foreach (DictionaryEntry de in playersPLID)
            {
                if ((int)de.Key == PLID)
                {
                    continue;
                }
                infoPlayer TcurrInfoPlayer = (infoPlayer)de.Value;
                // I'am behind
                if (currInfoPlayer.currPos < TcurrInfoPlayer.currPos )
                {
                    flagLast = false;
                    break;
                }
            }
            if (flagLast)
            {
                currInfoPlayer.UNameBehind = "";
                currInfoPlayer.gapBehind = "";
                newCfg.executeFunction("OnNewGapPlayerBehind", currInfoPlayer,par);

            }
            foreach (DictionaryEntry de in playersPLID)
            {
                if ((int)de.Key == PLID)
                {
                    continue;
                }
                infoPlayer TcurrInfoPlayer = (infoPlayer)de.Value;
// I'am behind
                if (currInfoPlayer.currPos == TcurrInfoPlayer.currPos + 1)
                {
                    TcurrInfoPlayer.UNameBehind = currInfoPlayer.userName;
                    currInfoPlayer.UNameBefore = TcurrInfoPlayer.userName;
                    if (modifyOnlyPos)
                    {
                        currInfoPlayer.gapBefore = "";
                        TcurrInfoPlayer.gapBehind = "";
                        newCfg.executeFunction("OnNewGapPlayerBehind", TcurrInfoPlayer,par);
                        newCfg.executeFunction("OnNewGapPlayerBefore", currInfoPlayer,par);
                        return;
                    }
                    else
                    {
                        if (currInfoPlayer.currElapsedInfo.lap[split] == TcurrInfoPlayer.currElapsedInfo.lap[split])
                        {
                            currInfoPlayer.gapBefore = unitConv.LongToHMS(currInfoPlayer.currElapsedInfo.elapsedTime[split]
                                                            - TcurrInfoPlayer.currElapsedInfo.elapsedTime[split]);
                            TcurrInfoPlayer.gapBehind = currInfoPlayer.gapBefore;
                            newCfg.executeFunction("OnNewGapPlayerBehind", TcurrInfoPlayer,par);
                            newCfg.executeFunction("OnNewGapPlayerBefore", currInfoPlayer,par);

                        }
                        else
                        {
                            currInfoPlayer.gapBefore = (TcurrInfoPlayer.currElapsedInfo.lap[split]
                                                            - currInfoPlayer.currElapsedInfo.lap[split]).ToString() + " laps";
                            TcurrInfoPlayer.gapBehind = currInfoPlayer.gapBefore;
                            newCfg.executeFunction("OnNewGapPlayerBehind", TcurrInfoPlayer,par);
                            newCfg.executeFunction("OnNewGapPlayerBefore", currInfoPlayer,par);
                        }
                    }
                    return;
                }
                currInfoPlayer.UNameBehind = "";
                currInfoPlayer.gapBehind = "";
                newCfg.executeFunction("OnNewGapPlayerBehind", currInfoPlayer,par);

            }
        }
        public void loopButton(Configurator.lexConfigurator newCfg)
        {
            // Retrouver les infos de tous les joueurs pour faire le loop button
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                currInfoPlayer.playerBox.loopButton(currInfoPlayer, newCfg, blinkVisible );
            }
			blinkVisible = !blinkVisible;
        }
        public void loopTask(Configurator.lexConfigurator newCfg)
        {
            // Retrouver les infos de tous les joueurs
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                currInfoPlayer.loopTask( newCfg );
            }
        }
        public void globalButtonMessage(string id, int P_L, int P_T, int P_W, int P_H, int interligne, int secVisible, int P_TypeIn, int P_BSTyle, string P_caption, string P_buttonText, string P_onClick)
        {
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                if (P_buttonText == "[[TranslateEngine]]")
                    P_buttonText = lfsLang.replaceParmsLangStr(currInfoPlayer.idLang);

                currInfoPlayer.playerBox.create(id,
                                                currInfoPlayer.UCID,
                                                P_L,
                                                P_T,
                                                P_W,
                                                P_H,
                                                interligne,
                                                secVisible,
                                                P_TypeIn,
                                                P_BSTyle,
                                                P_caption,
                                                P_buttonText,
                                                P_onClick);
                currInfoPlayer.playerBox.show(id, currInfoPlayer.UCID);
            }
        }

        public void globalButtonClose(string argString)
        {
            // Retrouver les infos de tous les joueurs
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                currInfoPlayer.privateButtonClose(argString);
            }
        }
        public void raceRestart() // Race or Qualify restart
        {
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer =  (infoPlayer)de.Value;
                currInfoPlayer.idleticks = 0;
                currInfoPlayer.finishedPLID = -1;
                currInfoPlayer.allowIdleOnTrack = false;
                currInfoPlayer.lapsDone = 0;
                currInfoPlayer.currPos = 0;
                currInfoPlayer.currElapsedInfo = new infoPlayer.elpasedInfo(); ;
                currInfoPlayer.totalPitTime = 0;
                currInfoPlayer.pitStops = 0;
                currInfoPlayer.splitLast = 0;
                currInfoPlayer.lastIdxSplit = -1;
                currInfoPlayer.currSector = 1;
                currInfoPlayer.LastCrossedFinishLine = DateTime.Now;
                currInfoPlayer.MaxLapTime1Reached = false;
                currInfoPlayer.MaxLapTime2Reached = false;
                currInfoPlayer.OnPit = false;
                currInfoPlayer.NbFastDriveOnPit = 0;
                currInfoPlayer.NumCarResets = 0;
				currInfoPlayer.PenaltyNew = (int)InSim.pen.PENALTY_NONE;
				currInfoPlayer.PenaltyOld = (int)InSim.pen.PENALTY_NONE;
                currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;
// Add by Krayy                
                currInfoPlayer.bestSpeed = 0;
                currInfoPlayer.currSplit = 0;
                currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;
                currInfoPlayer.drivethroughcount = 0;
                currInfoPlayer.finishedPos = -1;
                currInfoPlayer.lapTime = 0;
                currInfoPlayer.lastSplitTime = -1;
                currInfoPlayer.maxLapSpeed = 0;
                currInfoPlayer.pitTime = 0;
                currInfoPlayer.racePBTime = 0;
                currInfoPlayer.raceTotalTime = 0;
				currInfoPlayer.old_x = 0;
				currInfoPlayer.old_y = 0;
				currInfoPlayer.old_z = 0;
			}
        }

        public int nbPlayerOnTrack  // Return votation for players
        {
            get
            {
                int IT = 0;
                foreach (DictionaryEntry de in playersUCID)
                {
                    infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                    if ( currInfoPlayer.OnTrack )
                        IT++;
                }
                return IT;
            }
        }
        public void voteClear()
        {
            foreach (DictionaryEntry de in playersUCID)
            {
                infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                currInfoPlayer.currVote = (int)InSim.vtn.VOTE_NONE;
            }
        }
        public int voteRestart  // Return votation for players
        {
            get
            {
                int VR = 0;
                foreach (DictionaryEntry de in playersUCID)
                {
                    infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                    if (currInfoPlayer.currVote == (int)InSim.vtn.VOTE_RESTART)
                        VR++;
                }
                return VR;
            }
        }
        public int voteQualify  // Return votation for players
        {
            get
            {
                int VQ = 0;
                foreach (DictionaryEntry de in playersUCID)
                {
                    infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                    if (currInfoPlayer.currVote == (int)InSim.vtn.VOTE_QUALIFY )
                        VQ++;
                }
                return VQ;
            }
        }
        public int voteEnd  // Return votation for players
        {
            get
            {
                int VE = 0;
                foreach (DictionaryEntry de in playersUCID)
                {
                    infoPlayer currInfoPlayer = (infoPlayer)de.Value;
                    if (currInfoPlayer.currVote == (int)InSim.vtn.VOTE_END )
                        VE++;
                }
                return VE;
            }
        }

    }
}
