using System;
using System.Windows.Forms;
using Smackbio;
using System.Threading;

namespace CSharpSample
{
    public partial class MainForm : Form
    {
        public delegate void delegateAddEvent(string msg);

        LogServer m_LogServer;          // Log Server
        Boolean m_Running;              // Is Running Monitor Thread?
        ManualResetEvent m_StopEvent;   // stop event
        public MainForm()
        {
            InitializeComponent();
            m_Running = false;
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (m_Running)
            {
                m_Running = false;
                m_StopEvent.WaitOne();
            }
        }

        private void cmdStartMonitoring_Click(object sender, EventArgs e)
        {
            cmdStartMonitoring.Enabled = false;
            cmdStopMonitoring.Enabled = true;
            txtPortNo.Enabled = false;

            m_Running = true;
            m_StopEvent = new ManualResetEvent(false);

            ThreadPool.QueueUserWorkItem(new WaitCallback(MonitoringThread));
        }

        private void cmdStopMonitoring_Click(object sender, EventArgs e)
        {
            m_Running = false;
            m_StopEvent.WaitOne();

            cmdStartMonitoring.Enabled = true;
            cmdStopMonitoring.Enabled = false;
            txtPortNo.Enabled = true;
        }

        private void cmdClearLogs_Click(object sender, EventArgs e)
        {
            lstEvents.Items.Clear();
            lblEventCount.Text = lstEvents.Items.Count.ToString();
        }

        public void OnAddEvent(String msg)
        {
            lstEvents.Items.Add(msg);
            lblEventCount.Text = lstEvents.Items.Count.ToString();
        }

        public Boolean OnTimeLog(
            String terminalType,
            Int32 terminalID,
            String serialNumber,
            Int32 transactionID,
            DateTime logTime,
            Int64 userID,
            Int32 doorID,
            String attendanceStatus,
            String verifyMode,
            Int32 jobCode,
            String antipass,
            Byte[] photo)
        {
            String msg;

            try
            {
                msg = "[" + terminalType + ":";
                msg += terminalID.ToString();
                msg += " SN=" + serialNumber + "] ";
                msg += "TimeLog";
                msg += "(" + transactionID.ToString() + ") ";
                msg += logTime.ToString() + ", ";
                msg += "UserID=" + String.Format("{0}, ", userID);
                msg += "Door=" + doorID.ToString() + ", ";
                msg += "AttendStat=" + attendanceStatus + ", ";
                msg += "VMode=" + verifyMode + ", ";
                msg += "JobCode=" + jobCode.ToString() + ", ";
                msg += "Antipass=" + antipass + ", ";
                if (photo == null)
                    msg += "Photo=No";
                else
                {
                    msg += "Photo=Yes ";
                    msg += "(" + Convert.ToString(photo.Length) + "bytes)";
                }
                BeginInvoke(new delegateAddEvent(OnAddEvent), msg);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public Boolean OnAdminLog(
            String terminalType,
            Int32 terminalID,
            String serialNumber,
            Int32 transactionID,
            DateTime logTime,
            Int64 adminID,
            Int64 userID,
            String action,
            Int32 result)
        {
            String msg;

            try
            {
                msg = "[" + terminalType + ":";
                msg += terminalID.ToString();
                msg += " SN=" + serialNumber + "] ";
                msg += "AdminLog";
                msg += "(" + transactionID.ToString() + ") ";
                msg += logTime.ToString() + ", ";
                msg += "AdminID=" + String.Format("{0}, ", adminID);
                msg += "UserID=" + String.Format("{0}, ", userID);
                msg += "Action=" + action + ", ";
                msg += "Status=" + String.Format("{0:D}", result);
                BeginInvoke(new delegateAddEvent(OnAddEvent), msg);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public Boolean OnAlarmLog(
            String terminalType,
            Int32 terminalID,
            String serialNumber,
            Int32 transactionID,
            DateTime logTime,
            Int64 userID,
            Int32 doorID,
            String alarmType)
        {
            String msg;
            try
            {
                msg = "[" + terminalType + ":";
                msg += terminalID.ToString();
                msg += " SN=" + serialNumber + "] ";
                msg += "AlarmLog";
                msg += "(" + transactionID.ToString() + ") ";
                msg += logTime.ToString() + ", ";//'at'
                msg += "UserID=" + String.Format("{0}, ", userID);
                msg += "Door=" + doorID.ToString() + ", ";
                msg += "Type=" + alarmType;
                BeginInvoke(new delegateAddEvent(OnAddEvent), msg);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public void OnPing(
            String terminalType,
            Int32 terminalID,
            String serialNumber,
            Int32 transactionID)
        {
            String msg;

            msg = "[" + terminalType + ":";
            msg += terminalID.ToString();
            msg += " SN=" + serialNumber + "] ";
            msg += "KeepAlive";
            msg += "(" + transactionID.ToString() + ") ";
            BeginInvoke(new delegateAddEvent(OnAddEvent), msg);
        }

        private void MonitoringThread(object state)
        {
            UInt16 portNum = Convert.ToUInt16(txtPortNo.Text); // Get port number.

            m_LogServer = new LogServer(portNum, OnTimeLog, OnAdminLog, OnAlarmLog, OnPing);   // Create and start log server.

            // Watch stop signal.
            while (m_Running)
            {
                Thread.Sleep(100);  // Simulate some lengthy operations.
            }

            m_LogServer.Dispose();  // Dispose log server
            m_StopEvent.Set();      // Signal the stopped event.
        }
    }
}