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()
        {
            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 == "192.168.85.202")
                        {
                            bool isConnected = axCZKEM1.Connect_Net(machine.MachineIp, Convert.ToInt32(machine.PortNumber));
                            if (isConnected)
                            {
                                axCZKEM1.EnableDevice(Convert.ToInt32(machine.MachineId), false);

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


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



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

                                    responses.AddRange(poolMachineData(machine.MachineIp, machine.PortNumber, Convert.ToInt16(machine.MachineId)));
                                    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(machine);

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

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

                                  
                                 

                                    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)));
                                    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;
        }

        public List<string> poolMachineDataColony(string ip, int port, int machineId)
        {
            List<string> responses = new List<string>();


            string mPath = string.Empty;

            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;
            int CountAttendance = 0;

            //Cursor = Cursors.WaitCursor;
            //Bconnect = axCZKEM1.Connect_Net(ip, Convert.ToInt32(port));
            //axCZKEM1.EnableDevice(machineId, false);//disable the device

            try
            {

                //axCZKEM1.RegEvent(Convert.ToInt32(machineId), 65535);//Here you can register the realtime events that you want to be triggered(the parameters 65535 means registering all)
                if (axCZKEM1.ReadAllGLogData(machineId))//read all the attendance records to the 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 the memory
                    {
                        DateTime date = new DateTime(idwYear, idwMonth, idwDay, idwHour, idwMinute, idwSecond);
                        try
                        {

                            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 + "");

                            //return response;

                        }
                        catch (Exception ex)
                        {
                            responses.Add(ex.Message.ToString());
                        }
                    }


                    // responses.Add(GetTotalFromMachine(machineId));
                    axCZKEM1.ClearGLog(machineId);
                    //axCZKEM1.EnableDevice(machineId, true);

                    // axCZKEM1.Disconnect();

                }
                else
                {
                    responses.Add("MACHINE : " + ip + " : NO DATA");
                    return responses;
                }
                return responses;
            }
            catch (Exception ex)
            {

                responses.Add(ex.Message.ToString());
                return responses;

            }
        }
        public List<string> poolMachineData(string ip, int port, int machineId)
        {
            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
            {
                // Connect and read attendance records
                if (axCZKEM1.ReadAllGLogData(machineId)) // 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 records
                    try
                    {
                        if (attendanceLogs.Count > 0)
                        {
                            attendanceDAO.BulkInsert(attendanceLogs, connection); // Bulk insert method
                            responses.Add($"Successfully inserted {attendanceLogs.Count} records for MACHINE: {ip}");
                        }
                        else
                        {
                            responses.Add($"MACHINE: {ip} - No attendance logs found.");
                        }
                    }
                    catch (Exception ex)
                    {
                        responses.Add($"Error during bulk insert: {ex.Message}");
                    }

                    // Clear logs from the machine
                    axCZKEM1.ClearGLog(machineId);
                }
                else
                {
                    responses.Add($"MACHINE: {ip} - No data available.");
                }

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


        public List<string> GetAllFaceInfo(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();
        }


    }
}