//*****************************************************************************
//该版本每位用户对应6组虹膜编码（6个左眼，6个右眼）2015.9.1修改
//*****************************************************************************
using IAiCamIrisLib;
using irisRefactor.IrisCamera;
using System;
using System.Collections;
using System.Data;
using System.IO;
using System.Windows.Forms;

namespace irisMemory
{
    public class IrisCodeListMgr
    {
        private static byte[] m_byLeft = null;
        private static byte[] m_byRight = null;

        private Hashtable m_htblUsers = null;
        private int m_IrisCodeCount = 0;
        private iCamIrisClass m_iCamIrisLib = new iCamIrisClass();
        
        /// <summary>
        /// 数据库注册的用户总数
        /// </summary>
        public int TotalUsers
        {
            get { return m_IrisCodeCount; }
        }


        /// <summary>
        /// 创建匹配用虹膜模板list，每位用户对应：3组左眼虹膜编码 & 3组右眼虹膜编码
        /// </summary>
        /// <param name="ds"> Data set </param>
        public void CreateList(DataSet ds)
        {
            //获取数据集中的用户总数
            m_IrisCodeCount = ds.Tables[0].Rows.Count; 

            //创建哈希表，用于存储用户Id信息
            m_htblUsers = new Hashtable();
                     
            //创建匹配用的全部用户虹膜编码codeList  
            m_byLeft = new byte[1024 * m_IrisCodeCount * 3];
            m_byRight = new byte[1024 * m_IrisCodeCount * 3];

            lock (m_byLeft)
            {
                lock (m_byRight)
                {
                    for (int iCounter = 0; iCounter < ds.Tables[0].Rows.Count; iCounter++)
                    {
                        //获取该用户全部虹膜编码
                        object icLeft = ds.Tables[0].Rows[iCounter]["LEFT_IRIS_CODE1"];
                        object icRight = ds.Tables[0].Rows[iCounter]["RIGHT_IRIS_CODE1"];

                        object icLeft2 = ds.Tables[0].Rows[iCounter]["LEFT_IRIS_CODE2"];
                        object icRight2 = ds.Tables[0].Rows[iCounter]["RIGHT_IRIS_CODE2"];

                        object icLeft3 = ds.Tables[0].Rows[iCounter]["LEFT_IRIS_CODE3"];
                        object icRight3 = ds.Tables[0].Rows[iCounter]["RIGHT_IRIS_CODE3"];


                        //获取该用户Id信息，添加到哈希表
                        string sUser = ds.Tables[0].Rows[iCounter]["PERSON_ID"].ToString();
                        m_htblUsers.Add(iCounter, sUser);

                        //将该用户的三组左眼虹膜编码依次粘贴至m_byLeft
                        if (System.DBNull.Value != icLeft)
                            Array.Copy((byte[])icLeft, 0, m_byLeft, iCounter * 3 * 1024, 1024);

                        if (System.DBNull.Value != icLeft2)
                            Array.Copy((byte[])icLeft2, 0, m_byLeft, (iCounter * 3 + 1) * 1024, 1024);

                        if (System.DBNull.Value != icLeft3)
                            Array.Copy((byte[])icLeft3, 0, m_byLeft, (iCounter * 3 + 2) * 1024, 1024);


                        //将该用户的三组右眼虹膜编码依次粘贴至m_byRight
                        if (System.DBNull.Value != icRight)
                            Array.Copy((byte[])icRight, 0, m_byRight, iCounter * 3 * 1024, 1024);

                        if (System.DBNull.Value != icRight2)
                            Array.Copy((byte[])icRight2, 0, m_byRight, (iCounter * 3 + 1) * 1024, 1024);

                        if (System.DBNull.Value != icRight3)
                            Array.Copy((byte[])icRight3, 0, m_byRight, (iCounter * 3 + 2) * 1024, 1024);

                    }
                }
            }

        }


        /// <summary>
        /// 通过匹配出的iMatchNumber获取到用户Id 
        /// </summary>
        /// <param name="index"> 参数index输入为匹配出的iMatchNumber，取值范围为1，2, 3 ...m_IrisCodeCount*6*2；
        /// <中间变量 indexHash> 中间量indexHash代表index在哈希表中的排号，取值范围为0，1, 2...m_IrisCodeCount 
        /// <returns> </returns> indexHash对应的用户Id
        /// eg1: iMatchNumber：1-12， 对应indexHash：0；
        /// eg2: iMatchNumber：13-24，对应indexHash：1;
        public string GetUserForIndex(int index) 
        {
            int indexHash;

            if (index % 6 != 0) indexHash = index / 6;
            else indexHash = index / 6 - 1;

            if ((indexHash > m_htblUsers.Count + 1) || (indexHash < 0))
                return "";

            return m_htblUsers[indexHash].ToString();

        }


        /// <summary>
        /// 识别设备捕捉到一只眼睛时的匹配
        /// <param name="byImage">  Iris image </param>
        /// <param name="fHammingDistance"> Hamming distance </param>
        /// <param name=" LeftRight"> Left or Right </param>
        /// <returns> 0 or >0 </returns>
        public int MatchOneEye(byte[] byImage, out float fHammingDistance, out int LeftRight)
        {
            int iRetval;
            object iIrisCode;
            int iMatchNumber = 0;
            fHammingDistance = 1;
            LeftRight = 0;

            
                //先利用4000对待识别图像进行长编码
                int RetCoding = m_iCamIrisLib.CreateLongIrisCode(byImage, out iIrisCode);

                if (RetCoding == 0)
                {
                    lock (m_byRight)
                    {
                        //与右眼逐一比对           
                        iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, (byte[])iIrisCode, m_byRight, m_IrisCodeCount * 3 * 2);

                        if (iRetval == 0 && iMatchNumber > 0)
                        {
                            m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                            LeftRight = 2;
                            return iMatchNumber;
                        }
                        else
                        {
                            lock (m_byLeft)
                            {
                                //如果右眼未匹配，再对左眼进行逐一比对
                                iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, iIrisCode, m_byLeft, m_IrisCodeCount * 3 * 2);

                                if (iRetval == 0 && iMatchNumber > 0)
                                {
                                    m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                                    LeftRight = 1;
                                    return iMatchNumber;
                                }
                            }
                        }
                    }

                }

                return 0;
            
        }


        /// <summary>
        /// 与左眼进行匹配
        /// <param name="byImage">  Iris image </param>
        /// <param name="fHammingDistance"> Hamming distance </param>
        /// <param name=" LeftRight"> Left or Right </param>
        /// <returns> 0 on failure </returns> iMatchNumber on success match
        public int MatchLeftEye(byte[] byImage, out float fHammingDistance)
        {
            int iRetval;
            object iIrisCode;
            int iMatchNumber = 0;
            fHammingDistance = 1;

            //先利用4000对待识别图像进行长编码
            int RetCoding = m_iCamIrisLib.CreateLongIrisCode(byImage, out iIrisCode);

            if (RetCoding == 0)//编码成功
            {
                //逐一比对           
                iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, (byte[])iIrisCode, m_byLeft, m_IrisCodeCount * 3 * 2);

                if (iRetval == 0 && 0 != iMatchNumber)
                {
                    m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                    return iMatchNumber;
                }

            }

            return 0;

        }

        /// <summary>
        ///  与右眼进行匹配
        /// </summary>
        /// <param name="byImage"></param>
        /// <param name="fHammingDistance"></param>
        /// <returns></returns>
        public int MatchRightEye(byte[] byImage, out float fHammingDistance)
        {
            int iRetval;
            object iIrisCode;
            int iMatchNumber = 0;
            fHammingDistance = 1;

            //先利用4000对待识别图像进行长编码
            int RetCoding = m_iCamIrisLib.CreateLongIrisCode(byImage, out iIrisCode);

            if (RetCoding == 0)//编码成功
            {
                //逐一比对           
                iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, (byte[])iIrisCode, m_byRight, m_IrisCodeCount * 3 * 2);

                if (iRetval == 0 && 0 != iMatchNumber)
                {
                    m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                    return iMatchNumber;
                }

            }

            return 0;

        }


        /// <summary>
        ///  与任意一只眼睛进行匹配
        /// </summary>
        /// <param name="byImage"></param>
        /// <param name="fHammingDistance"></param>
        /// <returns></returns>
        /// <summary>        
        public int MatchEitherEye(byte[] byImage, out float fHammingDistance)
        {
            int iRetval;
            object iIrisCode;
            int iMatchNumber = 0;
            fHammingDistance = 1;
            //LeftRight = 0;

            //先利用4000对待识别图像进行长编码
            int RetCoding = m_iCamIrisLib.CreateLongIrisCode(byImage, out iIrisCode);

            if (RetCoding == 0)
            {
                //与右眼逐一比对           
                iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, (byte[])iIrisCode, m_byRight, m_IrisCodeCount * 3 * 2);

                if (iRetval == 0 && iMatchNumber > 0)
                {
                    m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                    //LeftRight = 2;
                    return iMatchNumber;
                }

               //如果右眼未匹配，再对左眼进行逐一比对
                else
                {
                    iRetval = m_iCamIrisLib.MatchByLongIrisCode(out iMatchNumber, iIrisCode, m_byLeft, m_IrisCodeCount * 3 * 2);

                    if (iRetval == 0 && iMatchNumber > 0)
                    {
                        m_iCamIrisLib.GetInformation(Constants.RECOGNITION_HD, out fHammingDistance);
                        //LeftRight = 1;
                        return iMatchNumber;
                    }

                }

            }

            return 0;
        }


    }
}
