using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Net.NetworkInformation;
using System.Data.OracleClient;
using System.Diagnostics;
using MySql.Data.MySqlClient;


namespace ZktecoAttendenceService
{
    public partial class DevicePolling : Form
    {
        static MySqlConnection connection;

        static ConnectionClass ObjConnectionClass = new ConnectionClass();
        AttendanceDAO attendanceDAO = new AttendanceDAO();
        AttendanceMachineUserDAO attendanceMachineUserDAO = new AttendanceMachineUserDAO();
        WriteToTxtFile WriteFile_obj = new WriteToTxtFile();



        public zkemkeeper.CZKEMClass axCZKEM1 = new zkemkeeper.CZKEMClass();



        private bool bIsConnected = false;//the boolean value identifies whether the device is connected
        private int iMachineNumber = 0;//the serial number of the device.After connecting the device ,this value will be changed.
        DataTable dtMachines = new DataTable();
        DataTable dtPAth = new DataTable();

        List<string> empList = new List<string>();

        public DevicePolling()
        {
            InitializeComponent();
        }

        private void DevicePolling_Load(object sender, EventArgs e)
        {


            //timer1.Enabled = true;
            //timer1.Interval = 100;
            //timer1.Start();
            WriteFile_obj.WriteToFile("--Service is started at " + DateTime.Now, "ZKTECOAttendance");

            List<string> responses = StartPooling();
            foreach (var response in responses)
            {
                WriteFile_obj.WriteToFile(response, "ZKTECOAttendance");
            }
            WriteFile_obj.WriteToFile("--Service is stopped at " + DateTime.Now, "ZKTECOAttendance");

            Application.Exit();
        }
        
        public List<string> StartPooling()
        {
            try
            {
       
                List<string> responses = new List<string>();
                AttendanceMachineDAO attendanceMachineDAO = new AttendanceMachineDAO();
                AttendanceMachineUserDAO attendanceMachineUserDAO = new AttendanceMachineUserDAO(); 

                using (var connection = ObjConnectionClass.Connection())
                {
                    if (ObjConnectionClass.OpenConnection(connection))
                    {
                        var machines = attendanceMachineDAO.getAttendanceMachines(connection, "0");

                        foreach (var machine in machines)
                        {  
                            
                          // if ((machine.MachineIp == "172.16.53.4") || (machine.MachineIp == "172.16.53.9")) // For lahore warehouse

                          // if (machine.MachineIp == "192.168.90.191") // For lahore warehouse
                            {
                                bool isConnected = axCZKEM1.Connect_Net(machine.MachineIp, Convert.ToInt32(machine.PortNumber));
                                if (isConnected)
                                {
                                    axCZKEM1.EnableDevice(Convert.ToInt32(machine.MachineId), false);

                                    if (machine.MachineId != "100")
                                    {

                                        machine.Status = "SYNCING";
                                        attendanceMachineDAO.update(machine, connection);

                                        responses.AddRange(poolMachineData(machine.MachineIp, machine.PortNumber, Convert.ToInt16(machine.MachineId), connection));
                                        machine.Status = "IDLE";

                                        DateTime now = DateTime.Now.AddMinutes(-5);
                                        machine.LastSyncDate = now;
                                        Console.WriteLine(machine.MachineId + " => " + machine.LastSyncDate);
                                        attendanceMachineDAO.update(machine, connection);

                                        List<string> newResponses = new List<string>();
                                        GetAllFaceInfo(axCZKEM1, machine);

                                        attendanceMachineUserDAO.UpdateTotalEmpInMachines(machine.MachineId, empList.Count, connection);

                                        newResponses = attendanceMachineUserDAO.DeleteFromDbAndMachine(axCZKEM1, empList, machine, connection);
                                        if (newResponses.Count != 0)
                                        {
                                            responses.AddRange(newResponses);
                                        }

                                        //Saving the templates to the database
                                        //SaveTemplateDb saveTemplateDb = new SaveTemplateDb();
                                        //saveTemplateDb.InsertFaceIntoDb(machine, connection, axCZKEM1);

                                        empList = new List<string>();
                                        axCZKEM1.EnableDevice(Convert.ToInt32(machine.MachineId), true);
                                        Cursor = Cursors.Default;
                                        axCZKEM1.Disconnect();
                                    }
                                    else
                                    {
                                        machine.Status = "SYNCING";
                                        attendanceMachineDAO.updateColony(machine, connection);
                                        responses.AddRange(poolMachineDataColony(machine.MachineIp, machine.PortNumber, Convert.ToInt16(machine.MachineId),connection));
                                        machine.Status = "IDLE";

                                        DateTime now = DateTime.Now.AddMinutes(-5);
                                        machine.LastSyncDate = now;
                                        Console.WriteLine(machine.MachineId + " => " + machine.LastSyncDate);
                                        attendanceMachineDAO.updateColony(machine, connection);
                                        axCZKEM1.EnableDevice(Convert.ToInt32(machine.MachineId), true);
                                        Cursor = Cursors.Default;
                                        axCZKEM1.Disconnect();
                                    }
                                }
                                else
                                {
                                        responses.Add("MACHINE : " + machine.MachineIp + " : NOT CONNECTED");
                                    machine.Status = "NOT CONNECTED";
                                    attendanceMachineDAO.update(machine, connection);
                                }
                            }
                        }
                    }
                }

                return responses;
            }
            catch
            {
                Exception ex = new Exception();
                return null;
            }
        }

        public List<string> poolMachineDataColony(string ip, int port, int machineId, MySqlConnection connection)
        {
            List<string> responses = new List<string>();
            int idwErrorCode = 0;
            int countAttendance = 0;
            bool allRecordsSaved = true; // Flag to track if all records are saved successfully

            // Ensure axCZKEM1 is initialized before using it
            if (axCZKEM1 == null)
            {
                responses.Add($"MACHINE: {ip} - ERROR: SDK Not Initialized");
                return responses;
            }

            try
            {
                // Connect to the machine
                bool isConnected = axCZKEM1.Connect_Net(ip, port);
                if (!isConnected)
                {
                    axCZKEM1.GetLastError(ref idwErrorCode);
                    responses.Add($"MACHINE: {ip} - ERROR: Unable to connect (Code {idwErrorCode})");
                    return responses;
                }

                // Disable the device during data retrieval
                axCZKEM1.EnableDevice(machineId, false);
                string sdwEnrollNumber;
                int idwVerifyMode, idwInOutMode, idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond, idwWorkcode = 0;

                if (axCZKEM1.ReadAllGLogData(machineId)) // Read all attendance logs
                {
                   
                    while (axCZKEM1.SSR_GetGeneralLogData(machineId, out sdwEnrollNumber, out idwVerifyMode,
                        out idwInOutMode, out idwYear, out idwMonth, out idwDay, out idwHour, out idwMinute, out idwSecond, ref idwWorkcode))
                    {
                        try
                        {
                            DateTime date = new DateTime(idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond);
                            Attendance log = new Attendance(sdwEnrollNumber, date, false, machineId.ToString(), "1", ip, DateTime.Now);
                            attendanceDAO.AddColony(log, connection);
                            countAttendance++;
                            responses.Add($"MACHINE: {ip} - EMP NO: {sdwEnrollNumber} - TIME: {date}");
                        }
                        catch (Exception ex)
                        {
                            responses.Add($"MACHINE: {ip} - ERROR: {ex.Message}");
                            allRecordsSaved = false; // Mark as false if any record fails
                        }
                    }

                    // **Clear Attendance Logs Only If All Records Are Saved**
                    if (allRecordsSaved)
                    {
                        if (axCZKEM1.ClearGLog(machineId))
                        {
                            responses.Add($"MACHINE: {ip} - ATTENDANCE LOGS CLEARED SUCCESSFULLY");
                        }
                        else
                        {
                            axCZKEM1.GetLastError(ref idwErrorCode);
                            responses.Add($"MACHINE: {ip} - ERROR: Failed to clear logs (Code {idwErrorCode})");
                        }
                    }
                    else
                    {
                        responses.Add($"MACHINE: {ip} - LOGS NOT CLEARED: Some records failed to save.");
                    }
                }
                else
                {
                    axCZKEM1.GetLastError(ref idwErrorCode);
                    responses.Add($"MACHINE: {ip} - NO DATA (Error Code {idwErrorCode})");
                }
            }
            catch (Exception ex)
            {
                responses.Add($"MACHINE: {ip} - ERROR: {ex.Message}");
            }
            finally
            {
                // Re-enable the device and disconnect
                axCZKEM1.EnableDevice(machineId, true);
                axCZKEM1.Disconnect();
            }

            return responses;
        }
        int errorCode = 0;
        public List<string> poolMachineData(string ip, int port, int machineId, MySqlConnection connection)
        {
            List<string> responses = new List<string>();
            List<Attendance> attendanceLogs = new List<Attendance>();
            string sdwEnrollNumber = "";
            int idwVerifyMode = 0;
            int idwInOutMode = 0;
            int idwYear = 0;
            int idwMonth = 0;
            int idwDay = 0;
            int idwHour = 0;
            int idwMinute = 0;
            int idwSecond = 0;
            int idwWorkcode = 0;

            try
            {

                DateTime today = DateTime.Today;
                DateTime startTime = new DateTime(today.Year, today.Month, today.Day, 4, 0, 0); // 4:00 AM
                DateTime endTime = new DateTime(today.Year, today.Month, today.Day, 16, 0, 0); // 4:00 PM

                string startTimeFormatted = startTime.ToString("yyyy-MM-dd HH:mm:ss");
                string endTimeFormatted = endTime.ToString("yyyy-MM-dd HH:mm:ss");



                if(axCZKEM1.ReadGeneralLogData(machineId))

               // if (axCZKEM1.ReadAllGLogData(machineId))

                // Connect and read attendance records
                //if (axCZKEM1.ReadTimeGLogData(machineId, startTimeFormatted, endTimeFormatted)) // read all the attendance records into memory
                {
                    while (axCZKEM1.SSR_GetGeneralLogData(machineId, out sdwEnrollNumber, out idwVerifyMode,
                           out idwInOutMode, out idwYear, out idwMonth, out idwDay, out idwHour, out idwMinute, out idwSecond, ref idwWorkcode)) // get records from memory
                    {
                        DateTime date = new DateTime(idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond);
                        Attendance log = new Attendance(sdwEnrollNumber, date, false, machineId.ToString(), "1", ip, DateTime.Now);
                        attendanceLogs.Add(log); // Add to the bulk insert list

                        // Optionally log the retrieved record
                        responses.Add($"MACHINE: {ip}, EMP NO: {sdwEnrollNumber}, TIME: {date}");
                    }

                    // Perform bulk insert for all records2
                    try
                    {
                        if (attendanceLogs.Count > 0)
                        {
                            attendanceDAO.BulkInsert(attendanceLogs, connection); // Bulk insert method
                            responses.Add($"Successfully inserted {attendanceLogs.Count} records for MACHINE: {ip}");
                            // Clear logs from the machine
                            axCZKEM1.ClearGLog(machineId);
                        }
                        else
                        {
                            responses.Add($"MACHINE: {ip} - No attendance logs found.");
                        }


                    }
                    catch (Exception ex)
                    {
                        responses.Add($"Error during bulk insert: {ex.Message}");
                    }




                }
                else
                {
                    axCZKEM1.GetLastError(ref errorCode); // Get the last error code
                    responses.Add($"MACHINE: {ip} - No data available.");
                    //MessageBox.Show(errorCode.ToString());
                    ;
                }

                return responses;
            }
            catch (Exception ex)
            {
                responses.Add($"Error: {ex.Message}");
                return responses;
            }
        }


        public List<string> GetAllFaceInfo(zkemkeeper.CZKEMClass axCZKEM1, AttendanceMachine machine)
        {
            bool Bconnect = false;
            string sdwEnrollNumber = string.Empty, sName = string.Empty, sPassword = string.Empty;
            int iPrivilege = 0, iFaceIndex = 0, iFlag = 0, iTmpLength = 0;
            bool bEnabled = false;
            //Bconnect = axCZKEM1.Connect_Net(machine.MachineIp, Convert.ToInt32(machine.PortNumber));
            //axCZKEM1.EnableDevice(Convert.ToInt16(machine.MachineId), false);//disable the device


            //if (Bconnect == true)
            //{
            //objZkeeper.ReadAllUserID(machineNumber);
            axCZKEM1.ReadAllTemplate(Convert.ToInt16(machine.MachineId));
            while (axCZKEM1.SSR_GetAllUserInfo(Convert.ToInt16(machine.MachineId), out sdwEnrollNumber, out sName, out sPassword, out iPrivilege, out bEnabled))
            {
                empList.Add(sdwEnrollNumber);
            }

            //}
            return empList;
        }
        public string GetTotalFromMachine(int MachineID)
        {
            string response = "";

            string sdwEnrollNumber = string.Empty, sName = string.Empty, sPassword = string.Empty;
            int iPrivilege = 0, iFaceIndex = 0, iFlag = 0, iTmpLength = 0;
            bool bEnabled = false;

            axCZKEM1.ReadAllUserID(MachineID);
            //axCZKEM1.ReadAllTemplate(MachineID);

            int totalCount = 0;
            while (axCZKEM1.SSR_GetAllUserInfo(MachineID, out sdwEnrollNumber, out sName, out sPassword, out iPrivilege, out bEnabled))
            {

                totalCount++;
            }
            attendanceMachineUserDAO.UpdateTotalEmpInMachines(MachineID.ToString(), totalCount, connection);
            response = "MACHINE : " + MachineID + ", TOTAL EMP : " + totalCount + "";
            return response;
        }

        static string GetMonthName(int monthNum)
        {
            return GetMonthName(monthNum, false);
        }
        static string GetMonthName(int monthNum, bool abbreviate)
        {
            if (monthNum < 1 || monthNum > 12)
                throw new ArgumentOutOfRangeException("monthNum");
            DateTime date = new DateTime(1, monthNum, 1);
            if (abbreviate)
                return date.ToString("MMM");
            else
                return date.ToString("MMMM");
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            StartPooling();
        }


    }
}