using System;
using System.Collections.Generic;
using System.Text;
using Lumenera.USB;
using System.Drawing;
using System.Windows.Forms;
using System.Threading;
namespace LumeneraCamera
{
    class LucamClass
    {
        //Global variable
        private IntPtr hcam = IntPtr.Zero;           // Camera CHandle.
     //   private int callbackId;                                         // Hander to the call back.
   
                        
        public string windowTitle = "AVI PREVIEW";
        private delegate void RefreshDisplayDelegate();                 // setup a delegate.
   //     private RefreshDisplayDelegate screenHandler;                   // create the delegate
   //     private dll.LucamRgbPreviewCallback callbackHandler;            // Handler to the preview callback function.
        private bool isStreaming = false;     
        private bool isStreamingAVI = false;                        // Camera is streaming AVI.
        private bool isStreamingVideo = false;
        private int StreamWindowHdl = 0;                                // Camera streaming windows handle.
        private bool CameraStreamView = true;                           // Indicate that the stream is in window preview mode.
        private bool mono = false;
      // private AviPreview aviObject;                                   // AviWindows Object.
        private VideoPreview videoOjbect;



        /*
        +---------------------------------------------------------------------
        | Camera class plublic properties.
        +---------------------------------------------------------------------
         */
        
        public IntPtr CHandle
        {
            get
            {
                return (hcam);
            }
            set
            {
                hcam = value;
            }
        }                  // Camera handle property.(RW)
        public bool IsStreaming
        {
            get
            {
                return (isStreaming);
            }
        }                   // Camera current streaming status (RO)
        public bool IsStreamingVideo
        {
            get
            {
                return (isStreamingVideo  );
            }
            set
            {
                isStreamingVideo   = value;
                if (value)
                    isStreaming = true;
                else
                {
                    if (!isStreamingAVI)
                        isStreaming = false;
                }
            }
        }             // Camera video streaming status (RW)
        public bool IsStreamingAVI
        {
            get
            {
                return (isStreamingAVI );
            }
            set
            {
                isStreamingAVI  = value;
                if (value)
                    isStreaming = true;
                else
                {
                    if (!isStreamingVideo)
                        isStreaming = false;
                }
            }
        }               // Camera AVI recording streaming status (RW)
        public int CameraVideoPreviewWindows
        {
            get
            {
                return(StreamWindowHdl);
            }
            set
            {
                StreamWindowHdl = value;
            }
        }     // 
        public bool IsMono
        {
            get
            {
                return (mono);
            }
            set
            {
                mono = value;
            }
        }
        public bool IsUsingPreview      // Property to see if the video stream is displayed or not.
        {
            get
            {
                return (CameraStreamView);
            }
            set
            {
                CameraStreamView = value;
            }
        }
 
        public VideoPreview VideoObject
        {
            get
            {
                return (videoOjbect);
            }
            set
            {
                videoOjbect = value;
            }
        }
        // Class Constructor.
        public LucamClass()
        {
            Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("path") + @";C:\Program Files\Common Files\Lumenera Corporation");
            hcam = IntPtr.Zero;
          //  AviObject = new AviPreview();
        }
        ~LucamClass()
        {
            if (hcam != IntPtr.Zero)
            {
                if (IsStreamingVideo)
                    videoOjbect.VideoStreamStop();
                //if (isStreamingAVI)
                 //   AviObject.AviStreamStop();
               
                try
                {
                    api.CameraClose(hcam);
                    hcam = IntPtr.Zero;
                }
                catch
                {
                    hcam = IntPtr.Zero;
                }
            }
        }


        public bool CameraReset()
        {
            try
            {
                if (hcam != IntPtr.Zero)
                    api.CameraReset(hcam);
                return (true);
            }
            catch
            {
                return (false);
            }
        }
        public bool CameraOpen(int index)
        {
            try
            {
                hcam = api.CameraOpen(index);
                mono = false;
                if (api.GetProperty(hcam, dll.LucamProperty.COLOR_FORMAT) == (float)dll.LucamColorFormat.MONO)
                    mono = true;


                return (true);
            }
            catch
            {
                return (false);
            }
        }
        public bool CameraClose()
        {
            if (hcam == IntPtr.Zero) return (true);
            if (IsStreamingVideo)
                videoOjbect.VideoStreamStop();
            try
            {
                api.CameraClose(hcam);
                hcam = IntPtr.Zero;
                return (true);
            }
            catch
            {
                return (false);
            }
        }
        public bool CameraSelectUSB()
        {
            if (!dll.LucamSelectExternInterface(dll.LucamExternalInterface.USB2))
                return (false);
            return (true);
        }
        public bool CameraSelectGige()
        {
            if (!dll.LucamSelectExternInterface(dll.LucamExternalInterface.GIGEVISION))
                return (false);
            return (true);
        }
 
        public string CameraStringName()
        {
            string tmp = "";
            if (hcam != IntPtr.Zero)
            {
                tmp = CameraModelName(api.GetCameraId(hcam)) + "-->" + (api.GetSerialNumber(hcam)).ToString();
            }
            return (tmp);
        }
        public bool CameraFrameFormat(ref dll.LucamFrameFormat ff)
        {
            try
            {
                ff = api.GetFormat(hcam);
                return (true);
            }
            catch
            {
                return (false);
            }
        }
        public bool CameraWhiteBalance()
        {
            int nbFrameDelay = 5, width = 0, height = 0; ;
            if (!api.IsCameraValid(hcam)) return (false); // Not a valid camera handle exit.
            if (!IsStreaming ) return (false);       // Not streaming video exit.
            if (mono) return (false);                    // not white balance function on monochrome video.
            float frameRate = api.GetFrameRate(hcam);
            int delay = (int)(nbFrameDelay / frameRate) * 1000; //Delay to wait before having valid data for next white balance.
            try
            {
                api.GetResolution(hcam, out width, out height);
                for (int i = 0; i < 3; i++)
                {
                    if (!dll.LucamOneShotAutoWhiteBalance(hcam, 0, 0, width, height))
                    {
                        MessageBox.Show("No Analog WB capability");
                    }
                    
                    Thread.Sleep(delay);
                }
                for (int i = 0; i < 3; i++)
                {
                   if(! dll.LucamDigitalWhiteBalance(hcam, 0, 0, width, height ))
                   {
                       MessageBox.Show("No digital WB capability");
                   }
                   
                    Thread.Sleep(delay);
                }
                return (true);
            }
            catch
            {
                return (false);
            }
        }

        public bool AviConvertRawToStdVideo(string stdFile, string rawFile)
        {
            if (stdFile.Length == 0) return (false);     // Standard file name is invalid.
            if (rawFile.Length == 0) return (false);       // Raw file name is empty or invalid.

            if (!dll.LucamConvertRawAVIToStdVideo(hcam, stdFile, rawFile, dll.LucamAviFileType.AVI_STANDARD_24))
                return (false);
            return (true);
        }

        private string CameraModelName(int model)
        {
            string temp = "";
            CameraListing[] cameras = new CameraListing[]
            {
                new CameraListing(0x091, "Lu050"),
                new CameraListing(0x095, "Lu050"),
                new CameraListing(0x090, "Lu056"),
                new CameraListing(0x093, "Lu056"),
                new CameraListing(0x06c, "Lu070"),
                new CameraListing(0x07c, "Lu070"),
                new CameraListing(0x08c, "Lu070"),
                new CameraListing(0x085, "Lu080"),
                new CameraListing(0x012, "Lu100"),
                new CameraListing(0x052, "Lu100"),
                new CameraListing(0x092, "Lu100"),
                new CameraListing(0x09d, "Lu100"),
                new CameraListing(0x094, "Lu110"),
                new CameraListing(0x096, "Lu120"),
                new CameraListing(0x07a, "Lu130"),
                new CameraListing(0x09a, "Lu130"),
                new CameraListing(0x098, "Lu150"),
                new CameraListing(0x08a, "Lu160"),
                new CameraListing(0x04e, "Lu170"),
                new CameraListing(0x05e, "Lu170"),
                new CameraListing(0x06e, "Lu170"),
                new CameraListing(0x099, "Lu170"),
                new CameraListing(0x09e, "Lu170"),
                new CameraListing(0x062, "Lu176"),
                new CameraListing(0x072, "Lu176"),
                new CameraListing(0x072, "Lu176"),
                new CameraListing(0x017, "Lu200"),
                new CameraListing(0x097, "Lu200"),
                new CameraListing(0x09c, "Lu200"),
                new CameraListing(0x08d, "Lu270"),
                new CameraListing(0x087, "Lu300"),
                new CameraListing(0x09b, "Lu330"),
                new CameraListing(0x05b, "Lu370"),
                new CameraListing(0x07b, "Lu370"),
                new CameraListing(0x08b, "Lu370"),
                new CameraListing(0x081, "Lu500"),
                new CameraListing(0x086, "Lu620"),
                new CameraListing(0x189, "Lw015"),
                new CameraListing(0x18c, "Lw070"),
                new CameraListing(0x184, "Lw080"),
                new CameraListing(0x196, "Lw120"),
                new CameraListing(0x11a, "Lw130"),
                new CameraListing(0x19a, "Lw130"),
                new CameraListing(0x10a, "Lw160"),
                new CameraListing(0x18a, "Lw160"),
                new CameraListing(0x19e, "Lw170"),
                new CameraListing(0x15e, "Lw175"),
                new CameraListing(0x110, "Lw230"),
                new CameraListing(0x180, "Lw230"),
                new CameraListing(0x1c0, "Lw230"),
                new CameraListing(0x1c6, "Lw250"),
                new CameraListing(0x16d, "Lw290"),
                new CameraListing(0x1cd, "Lw290"),
                new CameraListing(0x19b, "Lw330"),
                new CameraListing(0x1c7, "Lw450"),
                new CameraListing(0x1ce, "Lw530"),
                new CameraListing(0x115, "Lw570"),
                new CameraListing(0x1c5, "Lw570"),
                new CameraListing(0x186, "Lw620"),
                new CameraListing(0x1c8, "Lw11050"),
                new CameraListing(0x1ca, "Lw11050"),
                new CameraListing(0x1c9, "Lw16050"),
                new CameraListing(0x01e, "INFINITY 1"),
                new CameraListing(0x031, "INFINITY 1"),
                new CameraListing(0x0a1, "INFINITY 1"),
                new CameraListing(0x0b1, "INFINITY 1"),
                new CameraListing(0x0e1, "INFINITY 1"),
                new CameraListing(0x1a6, "INFINITY 1"),
                new CameraListing(0x1ac, "INFINITY 1"),
                new CameraListing(0x1e5, "INFINITY 1"),
                new CameraListing(0x0a2, "INFINITY 2"),
                new CameraListing(0x0b2, "INFINITY 2"),
                new CameraListing(0x4f7, "INFINITY 1-2CB"),
                new CameraListing(0x132,"INFINITY 2"),
                new CameraListing(0x144, "INFINITY 2"),
                new CameraListing(0x159, "INFINITY 2"),
                new CameraListing(0x1a7, "INFINITY 2"),
                new CameraListing(0x1b2, "INFINITY 2"),
                new CameraListing(0x1b7, "INFINITY 2"),
                new CameraListing(0x01b, "INFINITY 3"),
                new CameraListing(0x033, "INFINITY 3"),
                new CameraListing(0x0a3, "INFINITY 3"),
                new CameraListing(0x0b3, "INFINITY 3"),
                new CameraListing(0x0e3, "INFINITY 3"),
                new CameraListing(0x135, "INFINITY 3"),
                new CameraListing(0x15a, "INFINITY 3"),
                new CameraListing(0x1af, "INFINITY 3"),
                new CameraListing(0x1b5, "INFINITY 3"),
                new CameraListing(0x044, "INFINITY 4"),
                new CameraListing(0X0a4, "INFINITY 4"),
                new CameraListing(0x0b4, "INFINITY 4"),
                new CameraListing(0x168, "INFINITY 4"),
                new CameraListing(0x1a8, "INFINITY 4"),
                new CameraListing(0x1ab, "INFINITY 4"),
                new CameraListing(0x1aa, "INFINITY 4"),
                new CameraListing(0x1f9, "INFINITY 4"),
                new CameraListing(0x0a5, "INFINITY 5"),
                new CameraListing(0x0b5, "INFINITY 5"),
                new CameraListing(0x0ba, "INFINITY 5"),
                new CameraListing(0x020, "INFINITY X"),
                new CameraListing(0x040, "INFINITY X"),
                new CameraListing(0x0a0, "INFINITY X"),
                new CameraListing(0x0b0, "INFINITY X"),
                new CameraListing(0x0e0, "INFINITY X"),
                new CameraListing(0x129, "INFINITY X"),
                new CameraListing(0x1a9, "INFINITY X"),
                new CameraListing(0x1b9, "INFINITY X"),
                new CameraListing(0x46c, "Lu070"),
                new CameraListing(0x49a, "Lv130"),
                new CameraListing(0x02e, "Lv170"),
                new CameraListing(0x49e, "Lv170"),
                new CameraListing(0x480, "Lv230"),
                new CameraListing(0x487, "Lv900"),
                new CameraListing(0x49f, "Lw110"),
                new CameraListing(0x48f, "Lw310"),
                new CameraListing(0x4ce, "Lw560"),
                new CameraListing(0x432, "INFINITY 1"),
                new CameraListing(0x4a2, "INFINITY 1"),
                new CameraListing(0x4b1, "INFINITY 1"),
                new CameraListing(0x460, "INFINITY 2"),
                new CameraListing(0x462, "INFINITY 2"),
                new CameraListing(0x4ae, "INFINITY 2"),
                new CameraListing(0x464, "INFINITY 3"),
                new CameraListing(0x465, "INFINITY 3"),
                new CameraListing(0x461, "INFINITY Lite"),
                new CameraListing(0x463, "INFINITY X"),
                new CameraListing(0x083, "PhotoID"),
                new CameraListing(0x1dc, "SKYnyx 2-0"),
                new CameraListing(0x1d0, "SKYnyx 2-2"),
                new CameraListing(0x1da, "SKYnyx 2-1"),
                new CameraListing(0x27c, "Lm070"),
                new CameraListing(0x28c, "Lm070"),
                new CameraListing(0x264, "Lm080"),
                new CameraListing(0x284, "Lm080"),
                new CameraListing(0x279, "Lm130"),
                new CameraListing(0x27a, "Lm130"),
                new CameraListing(0x29a, "Lm130"),
                new CameraListing(0x269, "Lm160"),
                new CameraListing(0x26a, "Lm160"),
                new CameraListing(0x28a, "Lm160"),
                new CameraListing(0x2c5, "Lm570"),
                new CameraListing(0x2c8, "Lm11050"),
                new CameraListing(0x384, "Lc080"),
                new CameraListing(0x36e, "Lc170"),
                new CameraListing(0x39e, "Lc170"),
                new CameraListing(0x38d, "Lc270"),
                new CameraListing(0x38b, "Lc370"),
                new CameraListing(0x3ad, "INFINITY Lite"),
                new CameraListing(0x40000, "Lg unprogrammed"),
                new CameraListing(0x40080, "Lg230ii"),
                new CameraListing(0x400c8, "Lg11050"),
                new CameraListing(0x400ca, "Lg11050ii"),
                new CameraListing(0x401ce, "Lg565")   
            };

            foreach (CameraListing b in cameras)
            {
                if (b.ModelID == model)
                    temp = b.Name;
            }
            if (temp == "")
                temp = "Unkown";
            return (temp);

        }
        public bool fillComboWithCameraList(ref ComboBox myCombo)
        {
            string tmp;
            int nbCamera = dll.LucamNumCameras();       // Get number of cameras.
            dll.LucamVersion[] ver = new dll.LucamVersion[nbCamera];                               // Adjust array according to number of cameras founded..
            ver = api.EnumCameras();                                              // Get all cameras information.
            myCombo.Items.Clear();                      // Make sure Combo Box is empty.
            if (ver.Length <= 0)
            {
                MessageBox.Show("No camera connected!", "Error In Acquisitionner");
                return (false);
            }
            myCombo.Items.Add("None");
            // Fill Combo
            foreach (dll.LucamVersion a in ver)
            {
                tmp = CameraModelName(a.CameraId);
                tmp += " --> SN:" + a.SerialNumber.ToString();
                myCombo.Items.Add(tmp);
            }
            // Todo - change color on already connected item
            myCombo.SelectedIndex = 0;
            myCombo.SelectedItem = 0;
            return (true);
        }  //Fill Combo Box with available camera.
    }
    public struct CameraListing
    {
        public int ModelID;
        public string Name;

        public CameraListing(int model, string name)
        {
            this.ModelID = model;
            this.Name = name;
        }
    }
}
