//  
//  ftpDbsUpload.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.Threading;
using System.Data;
#if MONOSQLITE
    using Mono.Data.SqliteClient;
#else
    using System.Data.SQLite;
#endif
using System.Collections;
using WebCamService;



namespace LapperThreads
{
    public class ftpDbsUpload
    {
        static Object thisLock = new Object();


        public LFSDbs.DbsAccess dbCon;
        private string ftpServer = "localhost";
        private string ftpRemotePath = ".";
        private string ftpLogin = "anonymous";
        private string ftpPassword = "anonymous@anonymous.net";
        private string ftpFilename = "Filename";
        private string ftpFilenameDest = "Filename";
        private string dbName;
        private bool delayedUploadQuery = false;
        private string dateFormat = "dd/MM/yyyy";
        private int LapTimeUsedForPb;
        DateTime nextUploadDb = DateTime.Now.AddSeconds((double)LFSLapper.paramLapper.delayedSave);
        private int doExport = 1;
        private GLDebug.Debug myDebug;

        public ftpDbsUpload(GLDebug.Debug pmyDebug, string pdbName, string pftpServer, string pftpLogin, string pftpPassword, string pftpRemotePath, string dateFormat, int LapTimeUsedForPb)
        {
            this.myDebug = pmyDebug;
            this.LapTimeUsedForPb = LapTimeUsedForPb;
            this.ftpServer = pftpServer;
            this.ftpLogin = pftpLogin;
            this.ftpPassword = pftpPassword;
            this.ftpRemotePath = pftpRemotePath;
            this.dbName = pdbName;
            this.dateFormat = dateFormat;
            this.ftpFilename = this.dbName + ".elp";
            this.ftpFilenameDest = System.IO.Path.GetFileName( this.dbName ) + ".elp";

            this.dbCon = new LFSDbs.DbsAccess( myDebug, pdbName);
        }
        public void immediateUpload()
        {
            Monitor.Enter(this);
            doExport++;
            Monitor.Exit(this);
        }
        public void delayedUpload()
        {
            Monitor.Enter(this);
            delayedUploadQuery = true;
            Monitor.Exit(this);
        }
        public void SendGripDbsToFtp()
        {
            string allLapTime;
            string allDatePb;
            string allTimePb;
            string allSplit1Pb;
            string allSplit2Pb;
            string allSplit3Pb;
            string virg;
            string filepath = this.dbName + ".elp";

            myDebug.WriteLine("mss","Ftp Upload grip DB Thread Started...");
            DateTime nextUploadFile = DateTime.Now.AddSeconds((double)LFSLapper.paramLapper.delayedSave);

            while (true)
            {
                if (doExport > 0)
                {
                    lock (thisLock)
                    {

//                        Console.WriteLine("FTP upload DBS " + dbName );
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(filepath);
                        sw.WriteLine("<config>");
                        sw.WriteLine("version = 1.00");
                        sw.WriteLine("mode = hotlaps");
                        sw.WriteLine("LapTimeUsedForPb = " + this.LapTimeUsedForPb);
                        sw.WriteLine("</config>");
                        dbCon.executeNonQuery("BEGIN TRANSACTION");
                        IDataReader retQuery = dbCon.executeQuery("SELECT * FROM fi_epb");
                        while (retQuery.Read()){
                            long idEpb = retQuery.GetInt64( retQuery.GetOrdinal("idEpb"));
                            IDataReader retQuery2 = dbCon.executeQuery("SELECT * FROM fi_lpb WHERE idEpb = " + idEpb 
                                                                               + " ORDER BY lapTime                     " );
                            allLapTime = "";
                            allDatePb = "";
                            allTimePb = "";
                            allSplit1Pb = "";
                            allSplit2Pb = "";
                            allSplit3Pb = "";
                            virg = "";
                            while (retQuery2.Read()) {
                                allLapTime = allLapTime + virg + LFSLapper.unitConv.LongToHMS(retQuery2.GetInt64(retQuery2.GetOrdinal("lapTime")));
                                string lDate = retQuery2.GetString(retQuery2.GetOrdinal("date"));
                                int year = int.Parse(lDate.Substring(0, 4));
                                int month = int.Parse(lDate.Substring(5, 2));
                                int day = int.Parse(lDate.Substring(8, 2));
                                lDate = new DateTime(year, month, day).ToString(this.dateFormat);
                                allDatePb = allDatePb + virg + lDate;

                                allTimePb = allTimePb + virg + retQuery2.GetString( retQuery2.GetOrdinal("time"));
                                allSplit1Pb = allSplit1Pb + virg 
                                        + LFSLapper.unitConv.LongToHMS( retQuery2.GetInt64( retQuery2.GetOrdinal("split1")));
                                allSplit2Pb = allSplit2Pb + virg 
                                        + LFSLapper.unitConv.LongToHMS( retQuery2.GetInt64( retQuery2.GetOrdinal("split2")));
                                allSplit3Pb = allSplit3Pb + virg 
                                        + LFSLapper.unitConv.LongToHMS( retQuery2.GetInt64( retQuery2.GetOrdinal("split3")));
                                virg = ",";
                            }
                            retQuery2.Close();
                            retQuery2.Dispose();
                            sw.WriteLine(retQuery.GetString( retQuery.GetOrdinal("userName")));
                            sw.WriteLine(retQuery.GetString( retQuery.GetOrdinal("nickName")));
                            sw.WriteLine(retQuery.GetInt64( retQuery.GetOrdinal("laps")));
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("carName")));
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("trackName")));

                            string DatePb = retQuery.GetString(retQuery.GetOrdinal("date"));
                            int lyear = int.Parse(DatePb.Substring(0, 4));
                            int lmonth = int.Parse(DatePb.Substring(5, 2));
                            int lday = int.Parse(DatePb.Substring(8, 2));
                            DatePb = new DateTime(lyear, lmonth, lday).ToString(this.dateFormat);
                            sw.WriteLine(DatePb);
                            sw.WriteLine( retQuery.GetString(retQuery.GetOrdinal("time")));
                            //sw.WriteLine((retQuery.GetInt64(retQuery.GetOrdinal("pbLapTime"))));
                            sw.WriteLine(LFSLapper.unitConv.LongToHMS(retQuery.GetInt64(retQuery.GetOrdinal("pbLapTime"))));
                            sw.WriteLine(LFSLapper.unitConv.LongToHMS(retQuery.GetInt64(retQuery.GetOrdinal("pbLapTimeSplit1"))));
                            sw.WriteLine(LFSLapper.unitConv.LongToHMS(retQuery.GetInt64(retQuery.GetOrdinal("pbLapTimeSplit2"))));
                            sw.WriteLine(LFSLapper.unitConv.LongToHMS(retQuery.GetInt64(retQuery.GetOrdinal("pbLapTimeSplit3"))));

                            sw.WriteLine( allDatePb );
                            sw.WriteLine( allTimePb );
                            sw.WriteLine( allLapTime );
                            sw.WriteLine( allSplit1Pb );
                            sw.WriteLine( allSplit2Pb );
                            sw.WriteLine( allSplit3Pb );
                            sw.WriteLine( LFSLapper.unitConv.LongToHMS(retQuery.GetInt64( retQuery.GetOrdinal("pbSectorSplit1"))));
                            sw.WriteLine( LFSLapper.unitConv.LongToHMS(retQuery.GetInt64( retQuery.GetOrdinal("pbSectorSplit2"))));
                            sw.WriteLine( LFSLapper.unitConv.LongToHMS(retQuery.GetInt64( retQuery.GetOrdinal("pbSectorSplit3"))));
                            sw.WriteLine( LFSLapper.unitConv.LongToHMS(retQuery.GetInt64( retQuery.GetOrdinal("pbSectorSplitLast"))));
                        }
                        retQuery.Close();
                        retQuery.Dispose();
                        dbCon.executeNonQuery("COMMIT TRANSACTION");
                        sw.Close();
                        if (this.ftpServer != "" && this.ftpLogin != "")
                        {
                            FtpClient ftp = new FtpClient(this.ftpServer, this.ftpLogin, this.ftpPassword);
                            ftp.RemotePath = this.ftpRemotePath;
                            try
                            {
                                ftp.Login();
                            }
                            catch (Exception e)
                            {
                                
                                myDebug.WriteLine("err","Caught Error ftp.login:" + e.Message);
                                goto fin_loop;
                            }
                            try
                            {
                                // Upload Temp file to FTP
                                ftp.Upload( this.ftpFilename, this.ftpFilenameDest);
                            }
                            catch (Exception e)
                            {
                                myDebug.WriteLine("err","Caught Error ftp.Upload:" + e.Message);
                                System.Threading.Thread.Sleep(200);
                                goto fin_loop;
                            }
                            try
                            {
                                ftp.Close();
                            }
                            catch (Exception e)
                            {
                                myDebug.WriteLine("err","Caught Error ftp.Close:" + e.Message);
                                System.Threading.Thread.Sleep(200);
                                goto fin_loop;
                            }
                        }
                    fin_loop:
                        doExport = doExport + 0;
                    }
                    doExport--;
                }
                else
                {
                    System.Threading.Thread.Sleep(1000);
                    if ( delayedUploadQuery == true && DateTime.Now > nextUploadDb )
                    {
                        doExport++;
                        delayedUploadQuery = false;
                        nextUploadDb = DateTime.Now.AddSeconds((double)LFSLapper.paramLapper.delayedSave);
                    }
                }
            }

        }
        public void SendDriftDbsToFtp()
        {
            string filepath = this.dbName + ".elp";

            myDebug.WriteLine("mss","Ftp Upload drift DB Thread Started...");
            DateTime nextUploadFile = DateTime.Now.AddSeconds((double)LFSLapper.paramLapper.delayedSave);

            while (true)
            {
                if (doExport > 0)
                {
                    lock (thisLock)
                    {

//                        Console.WriteLine("FTP upload DBS " + dbName);
                        System.IO.StreamWriter sw = new System.IO.StreamWriter(filepath);
                        sw.WriteLine("<config>");
                        sw.WriteLine("version = 1.00");
                        sw.WriteLine("mode = drift");
                        sw.WriteLine("</config>");
                        dbCon.executeNonQuery("BEGIN TRANSACTION");
                        IDataReader retQuery = dbCon.executeQuery("SELECT * FROM fi_driftpb");
                        while (retQuery.Read())
                        {
/*

                            Console.WriteLine(retQuery.GetString(retQuery.GetOrdinal("userName")));
                            Console.WriteLine(retQuery.GetString(retQuery.GetOrdinal("driftPoints")));
                            Console.WriteLine(retQuery.GetString(retQuery.GetOrdinal("carName")));
                            Console.WriteLine(retQuery.GetString(retQuery.GetOrdinal("trackName")));
*/
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("userName")));
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("nickName")));
                            sw.WriteLine(retQuery.GetInt64(retQuery.GetOrdinal("driftPoints")));
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("carName")));
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("trackName")));
                            string DatePb = retQuery.GetString(retQuery.GetOrdinal("date"));
                            int lyear = int.Parse(DatePb.Substring(0, 4));
                            int lmonth = int.Parse(DatePb.Substring(5, 2));
                            int lday = int.Parse(DatePb.Substring(8, 2));
                            DatePb = new DateTime(lyear, lmonth, lday).ToString(this.dateFormat);
                            sw.WriteLine(DatePb);
                            sw.WriteLine(retQuery.GetString(retQuery.GetOrdinal("time")));

                        }
                        retQuery.Close();
                        retQuery.Dispose();
                        dbCon.executeNonQuery("COMMIT TRANSACTION");
                        sw.Close();
                        if (this.ftpServer != "" && this.ftpLogin != "")
                        {
                            FtpClient ftp = new FtpClient(this.ftpServer, this.ftpLogin, this.ftpPassword);
                            ftp.RemotePath = this.ftpRemotePath;
                            try
                            {
                                ftp.Login();
                            }
                            catch (Exception e)
                            {
                                myDebug.WriteLine("err","Caught Error ftp.login:" + e.Message);
                                goto fin_loop;
                            }
                            try
                            {
                                // Upload Temp file to FTP
                                ftp.Upload( this.ftpFilename , this.ftpFilenameDest);
                            }
                            catch (Exception e)
                            {
                                myDebug.WriteLine("err","Caught Error ftp.Upload:" + e.Message);
                                System.Threading.Thread.Sleep(200);
                                goto fin_loop;
                            }
                            try
                            {
                                ftp.Close();
                            }
                            catch (Exception e)
                            {
                                myDebug.WriteLine("err","Caught Error ftp.Close:" + e.Message);
                                System.Threading.Thread.Sleep(200);
                                goto fin_loop;
                            }
                        }
                    fin_loop:
                        doExport = doExport + 0;
                    }
                    doExport--;
                }
                else
                {
                    System.Threading.Thread.Sleep(1000);
                    if (delayedUploadQuery == true && DateTime.Now > nextUploadDb)
                    {
                        doExport++;
                        delayedUploadQuery = false;
                        nextUploadDb = DateTime.Now.AddSeconds((double)LFSLapper.paramLapper.delayedSave);
                    }
                }
            }

        }
    }
}
