	//  
//  readCfg.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.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using GLScript;
using LapperThreads;

namespace Configurator
{
    public enum typFunction
    {
        Event,
        Sub,
    }
    public enum typVar
    {
        str,
        num,
        ip,
    }
    enum configVarReadWrite
    {
        adminfile,
        adminemail,
        smtpserver,
        loginmail,
        passmail,
        messagetime,
        showplayercontrol,
        defaulttopcar,
        swearwordslist,
        swearwordsmax,
        handicapusers,
        swapside,
        autogears,
        shifter,
        helpbrake,
        axisclutch,
        autoclutch,
        mouse,
        kbnohelp,
        kbstabilised,
        customview,
        votelifesec,
        voterestart,
        votequalify,
        voteend,
        autorestartracesec,
        autorestartonfirstfinished,
        rotateeverynbraces,
        enablerotation,
        rotatetracks,
        rotatecars,
        showsplitpb,
        refreshqualusers,
        qualusers,
        maxfloodlines,
        maxfloodlinestime,
        maxsessionlaps,
        minanglevelocity,
        maxnbinstunt,
        maxallowedlaptime1,
        maxallowedlaptime2,
        onidletimeout1,
        idleexclude,
        onidletimeout2,
        realtimedriftscore,
        gooddriftscore,
        minimumdriftscore,
        minimumdriftspeed,
        minimumdriftangle,
        maximumdriftangle,
        accelerationstartspeed,
        accelerationendspeed,
        accelerationstartspeedmph,
        accelerationendspeedmph,
        accelerationprivatemaxtime,
        maxfastdriveonpit,
        pitwindowstart,
        pitwindowstop,
        maxcarresets,
        reordergrid,
		disttodo,

        accelerationstartspeed2,
        accelerationendspeed2,
        accelerationstartspeedmph2,
        accelerationendspeedmph2,
        accelerationprivatemaxtime2,
        detecthitobject, //Hit Objects
        displayobjectinfo, //Enable/Disable OnObjectInfo Event
        layoutfolder,
        registerWebsite,
        longtimeformat,
        shorttimeformat,

        //DebugSystem
        displayloops,
        displaysubs,
        displayevents,
        displaygetplayervar,
        displaysetplayervar,
        displaylappervar,
        displaylapperfunction,

        //Discord Vars
        discordtoken,
        discordchannelreceive,
        discordbotstatus,

        //StoredValue Database
        storeofflinedata,

        //LFSRestAPI Vars
        restapiclientid,
        restapiclientsecret,
}

    public class VLAPPER
    {
        public string Password;
        public string WorkingDir;
        public string LayoutFolder = "";
        public string superUsers;
        public string StoredValueDbs;
        public string AdminFile = "./admin.txt";
        public string TrackInfoFile;
        public bool TCPmode = true;
        public bool EnableRegisterWeb = true;
        public string RegisterWebsite = "";
        public string DateFormat = "dd/MM/yyyy";
        public string LongDateFormat = "dd m yyyy";
        public string LongTimeFormat = "HH:mm:ss"; //24 hour format  , hh:mm:ss = 12-hour format
        public string ShortTimeFormat = "HH:mm"; //24 hour format  , hh:mm = 12-hour format
        public string adminEmail = "";
        public string smtpServer = "";
        public string loginMail = "";
        public string passMail = "";
        public byte LFSLapperInsimVersion;

        public int MessageTime = 5000;
        public bool ShowPlayerControl = true;
        public string FtpServer = "";
        public string FtpLogin = "";
        public string FtpPasswd = "";
        public string FtpRemotePath = "";

        public string DefaultTopCar;
        public string PubStatIdk = "";
        // AUthorization
        public string Auth1 = "";
        public string Auth2 = "";
        public string Auth3 = "";
        public string Auth4 = "";
        public string Auth5 = "";
        public string Auth6 = "";
        public string Auth7 = "";
        public string Auth8 = "";
        public string Auth9 = "";
        public string Auth10 = "";
        public string AuthAllowPlayer = "All";
        public int AuthMinPlayer = 0;
        //SwearWordsList
        public string SwearWordsList = "";
        public int SwearWordsMax = 2;
        // HandicapCars
        public string HandicapCars = "";
        public string HandicapCarsTracks = "";
        public bool RefreshHandicapUsers = false;
        public string HandicapUsers = "";
        // Control Allowed 
        public string SwapSide = "*";
        public string AutoGears = "*";
        public string Shifter = "*";
        public string HelpBrake = "*";
        public string AxisClutch = "*";
        public string AutoClutch = "*";
        public string Mouse = "*";
        public string KbNoHelp = "*";
        public string KbStabilised = "*";
        public string CustomView = "*";
        // Votation
        public string InRaceLapsVoteMinMax = "0-9999999";
        public int VoteLifeSec = 30;

        public int VoteRestart = -1;
        public int VoteQualify = -1;
        public int VoteEnd = -1;
        // Rotation
        public int AutoRestartRaceSec = 0;
        public bool AutoRestartOnFirstFinished = false;
        public int RotateEveryNbRaces = 4;
        public bool EnableRotation = false;
        public string RotateTracks = "";
        public string RotateCars = "";
        // Connection
        // Splitting
        public bool ShowSplitPB = true;
        // List of user qualifying 
        public bool RefreshQualUsers = true;
        public string QualUsers = "";
        // Flood Actions
        public int MaxFloodLines = 4;
        public int MaxFloodLinesTime = 5000;
        // Session action
        public int MaxSessionLaps = 99999;
        //Spinning detection options
        public int MinAngleVelocity = 250;
        public int MaxNbInStunt = 32768;
        // to Slow user
        public int MaxAllowedLapTime1 = -1;

        public int MaxAllowedLapTime2 = -1;
        // Idling options
        public int OnIdleTimeout1 = 60;
        public string IdleExclude = "";
        public int OnIdleTimeout2 = 120;

        // Display Objectinfo (Event OnObjectinfo)
        public int DisplayObjectInfo = -1;

        //Trigger OnPlayerFlagEvent
        public int PlayerFlagEvent = -1;

        //Turn on/off join Requests
        public int ReceiveJoinRequest = -1;

        //Turn on/off AI joining
        public int DisableAI = -1;

        // Drifting
        public string DriftDatabase = "./Databases/PBdrift";
        public int GoodDriftScore = 4000;
        public int RealTimeDriftScore = -1;
        public int MinimumDriftScore = 10;
        public int MinimumDriftSpeed = 50;
        public int MinimumDriftAngle = 15;
        public int MaximumDriftAngle = 100;
        // Hotlapping options
        public string GripDatabase = "./Databases/PBgrip";
        public int LapTimeUsedForPb = 1;
        // Acceleration options
        public double AccelerationStartSpeed = 1;
        public double AccelerationEndSpeed = 100;
        public double AccelerationStartSpeedMph = 1;
        public double AccelerationEndSpeedMph = 60;
        public double AccelerationPrivateMaxTime = 10;
        // Acceleration2 options
        public double AccelerationStartSpeed2 = 100;
        public double AccelerationEndSpeed2 = 160;
        public double AccelerationStartSpeedMph2 = 60;
        public double AccelerationEndSpeedMph2 = 100;
        public double AccelerationPrivateMaxTime2 = 15;
        //Object Hit
        public string DetectHitObject = ""; //No objects that will be detected
        // Penalties
        public int MaxFastDriveOnPit = 99999;

        // Pit windows
        public int PitWindowStart = 0;
        public int PitWindowStop = 0;

        // Car Resets
        public int MaxCarResets = 0;

        public string ReorderGrid = "LFS";

        // dist to do in meter to trigger OnDistDone event
        public int distToDo = -1;

        public string AllowedCars = "";

        //DebugMessages
        public int DisplayLoops = 0;
        public int DisplaySubs = 0;
        public int DisplayEvents = 0;
        public int DisplayGetPlayerVar = 0;
        public int DisplaySetPlayerVar = 0;
        public int DisplayLapperVar = 0;
        public static Int32 DisplayLapperFunction = 0;

        //Discord Vars
        public string DiscordToken = "";
        public string DiscordChannelReceive = "";
        public string DiscordBotStatus = "";

        //LFS RestAPI
        public string RestAPIClientID = "";
        public string RestAPIClientSecret = "";

        public string ListOfModInfo = "";

        //Allowed Modded Cars
        public int AmountofModdedCars = 0;
    }

    public class lexConfigurator
    {
        class eventProperties
        {
            public string varArgs;
            public eventProperties(string pvarArgs)
            {
                varArgs = pvarArgs;
            }
        }
        public VLAPPER varsLapper;
        public GLScript.GLApp CurrApp;
        private LFSLapper.lang lfsLang;
        public System.Collections.ArrayList Tasks = new System.Collections.ArrayList();
        public System.Collections.ArrayList layouts = new System.Collections.ArrayList();
        public System.Collections.ArrayList ListOfAllowedModdedCars = new System.Collections.ArrayList();
        public List<LFSRestAPI.ModCarEntry> ListOfModsFromAPI = new List<LFSRestAPI.ModCarEntry>();

        LFSLapper.infoPlayer currInfoPlayer;
        private GLDebug.Debug myDebug;
        private Hashtable eventAllowed = new Hashtable();

        public lexConfigurator(GLDebug.Debug pmyDebug, LFSLapper.lang plfsLang)
        {

            varsLapper = new VLAPPER();
            myDebug = pmyDebug;

            CurrApp = new GLApp(myDebug, "");
            lfsLang = plfsLang;

            eventAllowed["OnMSO"] = new eventProperties("$text,$userName");
            eventAllowed["OnLapperStart"] = new eventProperties("");
            eventAllowed["OnAuthAllowed"] = new eventProperties("$userName");
            eventAllowed["OnAuthNotAllowed"] = new eventProperties("$userName");
            eventAllowed["OnAuthReached"] = new eventProperties("$userName");
            eventAllowed["OnSwearWords1"] = new eventProperties("$userName");
            eventAllowed["OnSwearWords2"] = new eventProperties("$userName");
            eventAllowed["OnToLowHandicap"] = new eventProperties("$userName");
            eventAllowed["OnNotMatchFlags"] = new eventProperties("$userName");
            eventAllowed["OnVoteRestartChange"] = new eventProperties("");
            eventAllowed["OnVoteRestartReach"] = new eventProperties("");
            eventAllowed["OnVoteRestartZero"] = new eventProperties("");
            eventAllowed["OnVoteQualifyChange"] = new eventProperties("");
            eventAllowed["OnVoteQualifyReach"] = new eventProperties("");
            eventAllowed["OnVoteQualifyZero"] = new eventProperties("");
            eventAllowed["OnVoteEndChange"] = new eventProperties("");
            eventAllowed["OnVoteEndReach"] = new eventProperties("");
            eventAllowed["OnVoteEndZero"] = new eventProperties("");
            eventAllowed["OnConnect"] = new eventProperties("$userName");
            eventAllowed["OnDisConnect"] = new eventProperties("$userName,$reason");
            eventAllowed["OnSplit1"] = new eventProperties("$userName");
            eventAllowed["OnSplit2"] = new eventProperties("$userName");
            eventAllowed["OnSplit3"] = new eventProperties("$userName");
            eventAllowed["OnLap"] = new eventProperties("$userName");
            eventAllowed["OnSpbSplit1"] = new eventProperties("$userName");
            eventAllowed["OnSpbSplit2"] = new eventProperties("$userName");
            eventAllowed["OnSpbSplit3"] = new eventProperties("$userName");
            eventAllowed["OnSpbLast"] = new eventProperties("$userName");
            eventAllowed["OnFlood"] = new eventProperties("$userName");
            eventAllowed["OnRaceStart"] = new eventProperties("$NumP");
            eventAllowed["OnRaceEnd"] = new eventProperties("");
            eventAllowed["OnMaxSessionLaps"] = new eventProperties("$userName");
            eventAllowed["OnAngleVelocity"] = new eventProperties("$userName");
            eventAllowed["OnMaxNbInStunt"] = new eventProperties("$userName");
            eventAllowed["OnMaxAllowedLapTime1"] = new eventProperties("$userName");
            eventAllowed["OnMaxAllowedLapTime2"] = new eventProperties("$userName");
            eventAllowed["OnIdle1"] = new eventProperties("$userName");
            eventAllowed["OnIdle2"] = new eventProperties("$userName");
            eventAllowed["OnDriftPB"] = new eventProperties("$userName");
            eventAllowed["OnDriftLap"] = new eventProperties("$userName");
            eventAllowed["OnDriftScore"] = new eventProperties("$userName");
            eventAllowed["OnDriftTooLow"] = new eventProperties("$userName");
            eventAllowed["OnGoodDrift"] = new eventProperties("$userName");
            eventAllowed["OnDriftResetScore"] = new eventProperties("$userName");
            eventAllowed["OnPB"] = new eventProperties("$userName");
            eventAllowed["OnPBQual"] = new eventProperties("$userName");
            eventAllowed["OnAcceleration"] = new eventProperties("$userName");
            eventAllowed["OnAcceleration2"] = new eventProperties("$userName");
            eventAllowed["OnBeginPit"] = new eventProperties("$userName");
            eventAllowed["OnEndPit"] = new eventProperties("$userName");
            eventAllowed["OnPit"] = new eventProperties("$userName");
            eventAllowed["OnNotPitWindow"] = new eventProperties("$userName");
            eventAllowed["OnBeginPitWindow"] = new eventProperties("$userName");
            eventAllowed["OnEndPitWindow"] = new eventProperties("$userName");
            eventAllowed["OnFastDriveOnPitL1"] = new eventProperties("$userName");
            eventAllowed["OnFastDriveOnPitL2"] = new eventProperties("$userName");
            eventAllowed["OnMaxFastDriveOnPit"] = new eventProperties("$userName");
            eventAllowed["OnFalseStartL1"] = new eventProperties("$userName");
            eventAllowed["OnFalseStartL2"] = new eventProperties("$userName");
            eventAllowed["OnLeaveRace"] = new eventProperties("$userName");
            eventAllowed["OnRotateCar"] = new eventProperties("");
            eventAllowed["OnRotateTrack"] = new eventProperties("");
            eventAllowed["OnNewGapPlayerBehind"] = new eventProperties("$userName,$split");
            eventAllowed["OnNewGapPlayerBefore"] = new eventProperties("$userName,$split");
            eventAllowed["OnChangePos"] = new eventProperties("$userName,$lastPos,$currPos");
            eventAllowed["OnQualStart"] = new eventProperties("");
            eventAllowed["OnNewPlayerJoin"] = new eventProperties("$userName");
            eventAllowed["OnChangeTyres"] = new eventProperties("$userName,$FL_Changed,$FR_Changed,$RL_Changed,$RR_Changed");
            eventAllowed["OnFinish"] = new eventProperties("$userName");
            eventAllowed["OnResult"] = new eventProperties("$userName,$flagConfirm");
            eventAllowed["OnCarReset"] = new eventProperties("$userName");
            eventAllowed["OnMaxCarResets"] = new eventProperties("$userName");
            eventAllowed["OnExitPitLane"] = new eventProperties("$userName");
            eventAllowed["OnEnterPitLane"] = new eventProperties("$userName,$reason");
            eventAllowed["OnNameChange"] = new eventProperties("$userName,$oldNickName,$newNickName");
            eventAllowed["OnDistDone"] = new eventProperties("$userName");
            eventAllowed["OnPracStart"] = new eventProperties("$NumP");
            eventAllowed["OnButtonFunction"] = new eventProperties("$userName,$SubT");
            eventAllowed["OnREO"] = new eventProperties("$NumP, $ReqI, $currRaceOrder");
            eventAllowed["OnObjectHit"] = new eventProperties("$userName,$ObjectFlag,$ObjectHitTime,$Object_X,$Object_Y,$Object_Z,$ObjectType,$ObjectInDex,$ContactSpeed");//New
            eventAllowed["OnCrossingChecker"] = new eventProperties("$userName,$Flags,$Time,$Object,$UserSpeed,$CircleIndex");//New
            eventAllowed["OnCarContact"] = new eventProperties("$PlayerA,$PlayerB,$PlayerA_Speed,$PlayerB_Speed,$PlayerA_X,$PlayerB_X,$PlayerA_Y,$PlayerB_Y");//New
            eventAllowed["OnCarStateChanged"] = new eventProperties("$userName,$StateOfCar");//New
            eventAllowed["OnObjectInfo"] = new eventProperties("$userName,$NumO,$Action,$X,$Y,$Z,$Flags,$Type,$InDex,$Heading");//New
            eventAllowed["OnPlayerFlags"] = new eventProperties("$userName,$YellowFlag,$BlueFlag,$Value,$Time");
            eventAllowed["OnAdminCommandReport"] = new eventProperties("$userName,$IsAdmin,$Status,$Command,$Time");
            eventAllowed["OnHostMSO"] = new eventProperties("$Text,$Time");
            eventAllowed["OnNewJoinRequest"] = new eventProperties("$userName");
            eventAllowed["OnPlayerSelectCar"] = new eventProperties("$userName,$Car,$Time");
            eventAllowed["OnTakeOverCar"] = new eventProperties("$Player_Old,$Player_New,$Car");
            eventAllowed["OnLapValidation"] = new eventProperties("$userName,$HVLC,$Time");
            eventAllowed["OnInterfaceMode"] = new eventProperties("$userName,$Mode,$SubMode,$SelObject,$Time");
            eventAllowed["OnReceiveDiscordMessage"] = new eventProperties("$ChannelID,$ChannelName,$UNameID,$UName,$Text");

            eventAllowed["OnBlueFlag"] = new eventProperties("$userName,$userNameBehind,$Time");
            eventAllowed["OnYellowFlag"] = new eventProperties("$userName,$State,$Time");

            eventAllowed["OnPlayerHandicap"] = new eventProperties("$userName,$Flags,$H_Mass,$H_Tres");
        }
        public void setLocalVar(string idVar, string value )
        {
            // TODO
        }
        public void executeFunction(string funcName, LFSLapper.infoPlayer pcurrInfoPlayer, string[] par )
        {
            currInfoPlayer = pcurrInfoPlayer;
            if (currInfoPlayer != null && currInfoPlayer.functionsLapper.Contains(funcName))
            {
                GLApp.functionDef myFuncDef = (GLApp.functionDef)currInfoPlayer.functionsLapper[funcName];
                CurrApp.registerFunction(funcName, myFuncDef);
            }
            CurrApp.executeFunction(funcName, par);
                string values = "";
            //DEBUG SYSTEM
            if (eventAllowed.Contains(funcName))
            {
                if (varsLapper.DisplayEvents == 1)
                {
                    if ((currInfoPlayer != null) && (par != null))
                    {
                        foreach (string val in par)
                        {
                            if (values != "")
                                values = values + "," + val;
                            else
                                values = val;
                        }
                        Console.WriteLine("Event: " + funcName + " (" + values + ") ");
                    }
                    else if ((currInfoPlayer != null) && (par == null))
                    {
                        Console.WriteLine("Event: " + funcName + " (" + currInfoPlayer.userName + ") ");
                    }
                    else if (par != null)
                    {
                        foreach (string val in par)
                        {
                            if (values != "")
                                values = values + "," + val;
                            else
                                values = val;
                        }
                        Console.WriteLine("Event: " + funcName + "(" + values + ") ");
                    }
                }
            }
            else
            {
                if (varsLapper.DisplaySubs == 1)
                {
                    if (par == null)
                        Console.WriteLine("Sub: " + funcName + "()");
                    else if (par.Length < 1)
                    {
                        Console.WriteLine("Sub: " + funcName + "()");
                    }
                    else
                    {
                        foreach (string val in par)
                        {
                            if (values != "")
                                values = values + "," + val;
                            else
                                values = val;
                        }
                        Console.WriteLine("Sub: " + funcName + "(" + values + ") ");
                    }
                }
            }
        }
        public LFSLapper.infoPlayer getCurrInfoPlayer()
        {
            return currInfoPlayer;
        }
        public void addFunction(string id, string buff, string args )
        {
            CurrApp.registerFunction(id, buff, args,"", 1,"",null,null);
        }
        public void dumpNamesFunctions()
        {
            CurrApp.dumpNamesFunctions();
        }
        public bool load(string filepath )
        {
// Create Empty Defaults Events
            foreach (DictionaryEntry currEv in eventAllowed )
            {
                eventProperties evP = (eventProperties)currEv.Value;
                    CurrApp.registerFunction( (string)currEv.Key, "", evP.varArgs, "filepath", 1, "",null,null);
            }
            StringBuilder strSrc = new StringBuilder();
            string myPath = Path.GetDirectoryName(filepath);
            if (myPath == "")
                myPath = ".";
            load3(myPath, Path.GetFileName( filepath ), strSrc);
            tokenize( strSrc.ToString());
            return true;
        }
        private bool load3(string path, string filepath, StringBuilder strSrc)
        {
            string openFile = path + "/" + filepath;
            FileInfo File = new FileInfo(openFile);
            //			Console.WriteLine("load3: path = " + path + ", filepath = " + filepath );
            if (File.Exists)
            {
                String[] fileList = System.IO.Directory.GetFiles(Path.GetDirectoryName(openFile), Path.GetFileName(openFile));
                foreach (String fileName in fileList)
                {
                    load2(path, fileName, strSrc);
                }
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("WARNING: " + filepath + " doesn't exist!");
                myDebug.WriteLine("err", "Warning: Includes/" + filepath + " doesn't exist!");
                Console.ForegroundColor = ConsoleColor.White;
            }
            return true;
        }
        private bool load2(string path, string filepath, StringBuilder strSrc)
        {
//            string openFile = path + "/" + filepath;
            string openFile = filepath;
            int currLine = 0;
            StreamReader sr = null;
            FileInfo File = new FileInfo(openFile);
            
            try
            {
                sr = new StreamReader(openFile);
            }
            catch
            {

                myDebug.WriteLine("mss","Warning \"" + openFile + "\" doesn't exist!");
                return true;
            }
            
           
                sr = new StreamReader(openFile);
                strSrc.Append("FILE__ = \"" + filepath + "\"," + currLine + ";\n");
                while (!sr.EndOfStream)
                {
                    currLine++;
                    string line = sr.ReadLine().Trim();
                    if (line.Trim().ToLower().IndexOf("include") == 0)
                    {
                        int debInc = line.IndexOf('"');
                        int endInc = line.IndexOf('"', debInc + 1);
                        string file = line.Substring(debInc + 1, endInc - debInc - 1);

                        //                    string myPath = Path.GetDirectoryName(path + "/" + filepath);
                        string myPath = Path.GetDirectoryName(filepath);
                        if (myPath == "")
                            myPath = ".";
                        load3(myPath, file, strSrc);
                        strSrc.Append("FILE__ = \"" + filepath + "\"," + currLine + ";\n");
                        continue;
                    }
                    //				Console.WriteLine(currLine + ":" + line);
                    strSrc.Append(line + "\n");
                }
                sr.Close();
            return true;

        }
        public bool tokenize(string strSrc)
        {
            Type TvarsLapper = varsLapper.GetType();
            FieldInfo FIvarsLapper;
//            FileStream file;
            Scanner scnr;
            string currFile = "";
            int OfsetFile = 0;
            Hashtable globalConst = new Hashtable();

            try
            {
                
//                file = new FileStream(filepath, FileMode.Open);
//                scnr = new Scanner(file);
                scnr = new Scanner();
                scnr.SetSource(strSrc, 0);
            }
            catch (System.Exception ev)
            {
                myDebug.WriteLine("err","Error on opening config file: " + ev.Message);
                return false;
            }
            try
            {
                int tok;
                do
                {
                    tok = scnr.yylex();

//                    Console.WriteLine("#" + tok + ": " + scnr.yytext);
//					Console.WriteLine(scnr.YyLine + OfsetFile + ":" + scnr.yytext);
//					Console.WriteLine(scnr.YyLine + ":" + scnr.yytext);
					switch (tok)
					{
                        case GLScript.Scanner.E_LANG:
                            {
                                if ((tok = scnr.yylex()) != GLScript.Scanner.E_STRING)
                                    throw (new System.Exception("Syntax error in cfg file: Lang need lang id"));
                                string langId = UTILS.utils.unquote(scnr.yytext.ToLower());
                                while (true)
                                {
                                    tok = scnr.yylex();
                                    if (tok == GLScript.Scanner.E_ENDLANG || ( tok == Scanner.E_END && scnr.yytext.ToLower().Trim()== "endlang" ))
                                        break;
                                    if (tok != GLScript.Scanner.E_IDENT)
                                        throw (new System.Exception("Syntax error in cfg file: Need a item identification"));
                                    if (scnr.yytext == "FILE__")
                                    {
                                        tok = scnr.yylex(); //  = 
										tok = scnr.yylex(); // Value
										currFile = UTILS.utils.unquote(scnr.yytext);
										tok = scnr.yylex(); // ,
										tok = scnr.yylex(); // Ofset
										OfsetFile = int.Parse(scnr.yytext) - scnr.YyLine; // Offset for the file
										tok = scnr.yylex(); // ;
                                        continue;
                                    }
                                    string itemId = scnr.yytext;
                                    if ((tok = scnr.yylex()) != GLScript.Scanner.E_ASSIGN)
                                        throw (new System.Exception("Syntax error in cfg file: Need '=' "));
                                    string resultStr = "";
                                    while (true)
                                    {
                                        tok = scnr.yylex();
                                        if ( tok == GLScript.Scanner.E_STRING )
                                        {
                                            resultStr += UTILS.utils.unquote(scnr.yytext);
                                            continue;
                                        }
                                        if ( tok == GLScript.Scanner.E_POINT)
                                        {
                                            continue;
                                        }
                                        if (tok == GLScript.Scanner.E_SEMICOLON)
                                            break;
                                        if (tok == GLScript.Scanner.E_IDENT)
                                        {
                                            if (scnr.yytext == "FILE__")
                                            {
                                                tok = scnr.yylex(); //  = 
                                                tok = scnr.yylex(); // Value
                                                currFile = UTILS.utils.unquote(scnr.yytext);
												tok = scnr.yylex(); // ,
												tok = scnr.yylex(); // Ofset
												OfsetFile = int.Parse(scnr.yytext) - scnr.YyLine; // Offset for the file
												tok = scnr.yylex(); // ;
                                                continue;
                                            }
                                        }

                                        throw (new System.Exception("Syntax error in cfg file: Need string or '.' or ';'"));

                                    }
//									Console.WriteLine(resultStr);
									lfsLang.AddItem(langId, itemId, resultStr);
                                }

                            }
                            break;

                        case GLScript.Scanner.E_BEGIN_FUNCTION:
                            {
                                string identName = scnr.yytext.ToLower();
								int OfSetFunction = scnr.YyLine + OfsetFile;
//                                int lineCurr = scnr.GyyLine;
                                if ((tok = scnr.yylex()) != GLScript.Scanner.E_FUNCTION)
                                    throw (new System.Exception("Syntax error in cfg file: Event need Event identification"));

                                string ev = scnr.strBloc.Substring(0,scnr.strBloc.IndexOf('(' ) ).Trim();

                                if ( (identName == "event" || identName == "catchevent" ) && !eventAllowed.Contains( ev ))
                                    throw (new System.Exception("Event " + ev + " do not exist in LFSLapper"));

								string buffParam = string.Join( ",",(string[])scnr.args.ToArray(typeof(string)) );
								buffParam = buffParam.Trim();
                                string strBloc = "";
//                                scnr.BEGIN(4);
//                                scnr.BEGIN(0);
                                Hashtable localConst = new Hashtable();
								int oldYyLine = scnr.YyLine;
                                while (true)
                                {
                                    tok = scnr.yylex();
									if (oldYyLine != scnr.YyLine)
									{
										for( int i = oldYyLine; i < scnr.YyLine;i++ )
											strBloc += "\n";
										oldYyLine = scnr.YyLine;
									}
                                    string str = scnr.yytext;
//Console.WriteLine(scnr.YyLine + OfsetFile + ":" + scnr.yytext);
//Console.WriteLine(scnr.YyLine + ":" + scnr.yytext);

                                    if (tok == GLScript.Scanner.E_BEGIN_FUNCTION)
                                    {
                                        throw (new System.Exception("Unexpected function in event: " + ev));
                                    }
                                    if (tok == GLScript.Scanner.E_END_FUNCTION)
                                    {
                                        if (identName == "event" && str.ToLower() == "endevent")
                                            break;
                                        if (identName == "catchevent" && str.ToLower() == "endcatchevent")
                                            break;
                                        if (identName == "catchsub" && str.ToLower() == "endcatchsub")
                                            break;
                                        if (identName == "sub" && str.ToLower().Trim() == "endsub")
                                            break;
                                        throw (new System.Exception("Unexpected end function in event: " + ev));
                                    }
									if (tok == Scanner.E_CONST)
									{
										tok = scnr.yylex();
                                        if (tok != Scanner.E_IDENT)
                                            throw (new System.Exception("Unexpected token " + scnr.yytext + " in sub/event" + ev));
                                        string idConst = scnr.yytext;
                                        string buffer = "";
                                        while (true)
                                        {
                                            tok = scnr.yylex();
                                            if (tok == (int)Tokens.EOF || tok == Scanner.E_END)
                                                break;
                                            if (tok == Scanner.E_SEMICOLON)
                                                break;
                                            buffer += scnr.yytext;
                                        }
                                        localConst[idConst] = buffer;
                                        continue;
                                    }
									if (tok == Scanner.E_ARVAR)
									{
										str = scnr.strBloc;
									}
									if (tok == Scanner.E_FUNCTION)
									{
										str = scnr.strBloc;
									}

                                    strBloc += " " + str;

                                }
//                                scnr.BEGIN(0);

                                //Console.WriteLine("#" + tok + ": >----\n" + strBloc + "\n<------- ");
                                string attachToEvent = "";
                                if (identName == "catchevent" || identName == "catchsub")
                                {
                                    attachToEvent = ev;
									ev = ev + currFile + "-" + OfSetFunction.ToString();
                                }
								CurrApp.registerFunction(ev, strBloc, buffParam, currFile, OfSetFunction, attachToEvent, localConst, globalConst);
                            }
                            break;
                        case GLScript.Scanner.E_CONST:
                            {
                                tok = scnr.yylex();
                                if (tok != Scanner.E_IDENT)
                                    throw (new System.Exception("Syntax error in cfg file: const:" + scnr.yytext));
                                string idConst = scnr.yytext;
                                string buffer = "";
                                while (true)
                                {
                                    tok = scnr.yylex();
                                    if (tok == (int)Tokens.EOF || tok == Scanner.E_END)
                                        break;
                                    if (tok == Scanner.E_SEMICOLON)
                                        break;
                                    buffer += scnr.yytext;
                                }
                                globalConst[idConst] = buffer;
                            }
                            break;

                        case GLScript.Scanner.E_IDENT:
                            if (scnr.yytext == "FILE__")
                            {
                                tok = scnr.yylex(); //  = 
                                tok = scnr.yylex(); // Value
								currFile = UTILS.utils.unquote(scnr.yytext);
								tok = scnr.yylex(); // ,
								tok = scnr.yylex(); // Ofset
								OfsetFile = int.Parse(scnr.yytext) - scnr.YyLine; // Offset for the file
								tok = scnr.yylex(); // ;
							}
                            else
                                throw (new System.Exception("Syntax error in cfg file: " + scnr.yytext));
                            break;
                        case GLScript.Scanner.E_VAR:
                            try
                            {
                                string idVar = scnr.yytext.Substring(1);
                                if (scnr.yylex() != GLScript.Scanner.E_ASSIGN)
                                    throw (new System.Exception("Syntax error in cfg file: var $" + idVar + " need '='"));

                                tok = scnr.yylex();
                                int typParam = tok;

                                string strVal = scnr.yytext;
                                if (tok == GLScript.Scanner.E_MOINS || tok == GLScript.Scanner.E_NEG)
                                {
                                    tok = scnr.yylex();
                                    strVal += scnr.yytext;
                                    typParam = GLScript.Scanner.E_INTEGER;
                                }
                                if (scnr.yylex() != GLScript.Scanner.E_SEMICOLON)
                                    throw (new System.Exception("Syntax error in cfg file: var $" + idVar + " need '; at end of line'"));



                                FIvarsLapper = TvarsLapper.GetField(idVar);

                                if (FIvarsLapper == null)
                                {
                                    throw (new System.Exception("Variable $" + idVar + " not defined!"));
                                }
                                else
                                {
                                    string typVarsLapper = FIvarsLapper.FieldType.Name;
                                    if (typVarsLapper == "String" && typParam == GLScript.Scanner.E_IP)
                                    {
                                        //                                Console.WriteLine("Je set " + idVar + " Avec : " + strVal);
                                        FIvarsLapper.SetValue(varsLapper, strVal);
                                    }
                                    else if (typVarsLapper == "String" && typParam == GLScript.Scanner.E_STRING)
                                    {
                                        FIvarsLapper.SetValue(varsLapper, strVal.Substring(1, strVal.Length - 2));
                                    }
                                    else if (typVarsLapper == "Int32" && typParam == GLScript.Scanner.E_INTEGER)
                                    {
                                        try
                                        {
                                            FIvarsLapper.SetValue(varsLapper, int.Parse(strVal));
                                        }
                                        catch
                                        {
                                            throw (new System.Exception("Var $" + idVar + " is wrong type: Need Integer value"));
                                        }
                                    }
                                    else if (typVarsLapper == "Double" && (typParam == GLScript.Scanner.E_INTEGER || typParam == GLScript.Scanner.E_FLOAT))
                                    {
                                        try
                                        {
                                            FIvarsLapper.SetValue(varsLapper, double.Parse(strVal.Replace(".", System.Globalization.NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator)));
                                        }
                                        catch
                                        {
                                            throw (new System.Exception("Var $" + idVar + " is wrong type: Need float value"));
                                        }
                                    }
                                    else if (typVarsLapper == "Boolean" && (strVal.ToLower() == "true" || strVal.ToLower() == "false"))
                                    {
                                        try
                                        {
                                            FIvarsLapper.SetValue(varsLapper, bool.Parse(strVal));
                                        }
                                        catch
                                        {
                                            throw (new System.Exception("Var $" + idVar + " is wrong type: Need true or false value"));
                                        }

                                    }
                                    else
                                    {
                                        throw (new System.Exception("Var $" + idVar + " is wrong type: Need " + typVarsLapper + " value"));

                                        //                            CurrApp.GVAR.Set("ConfVar," + "\"" + idVar + "\"", new unionVal(0, "\"" + strVal + "\"", typVal.str));
                                        //                            CurrApp.GVAR.globVars["ConfVar"] = true;
                                        //                            Console.WriteLine(idVar + " = " + FIvarsLapper.GetValue(varsLapper));
                                    }
                                }
                            }
                            catch
                            {
                                myDebug.WriteLine("err", "Var not defined on file: \"" + currFile + "\" at line #" + (scnr.YyLine + OfsetFile).ToString());
                            }
                            break;
                        case GLScript.Scanner.E_END:
//                            file.Close();
                            return true;
                        default:
                            throw (new System.Exception("Syntax error in cfg file: line " + scnr.yytext + " Char " + scnr.yytext ));
                            


                    }
                } while (tok > (int)Tokens.EOF);
            }
            catch (System.Exception ev)
            {
                myDebug.WriteLine("err",ev.Message + " on file: \"" + currFile + "\" at line #" + ( scnr.YyLine + OfsetFile).ToString() );
                return false;
            }
            return true;

        }


    }
}