using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using System.Windows.Forms;
using icDecLibAztec_Net;


namespace DemoAztecSharp
{

    public partial class Form1 : Form
    {
        string OpenDialog_Filter = "All (*.jpg;*.jpeg;*.gif;*.bmp;*.tif)|*.jpg;*.jpeg;*.gif;*.bmp;*.tif;*.tiff|JPEG I" +
"mage File (*.jpg)|*.jpg|JPEG Image File (*.jpeg)|*.jpeg|Bitmaps (*.bmp)|*.bmp|Ti" +
"f Image File (*.tif)|*.tif;*.tiff";

        private Bitmap Picture;
        private Image SourcePicture=null;
        private EncodingInfo[ ] Info;
        private int CodePage;
        //        private ic_Decoder_Pro Decoder = new ic_Decoder_Pro(4000, 4000);
        private icAztecPro Decoder;
        private TAztec_Info  FAZ_Info = null;
        int AZCount;

        class ComboInfo
        {
            string Text;
            public int Codepage;
            public ComboInfo(string Cap,int CP)
            {
                Text = Cap;
                Codepage = CP;
            }
            public override string  ToString()
            {
                return Text;
            }
        }

        private void InitializeCodePages ( )
        {
            Info = Encoding.GetEncodings( );

          comboBox1.Items.Add( new ComboInfo("0  -  HexaDecimal",0));
            for ( int i = 0; i < Info.Length; i++ )
            {
                String S;
                
                int CP = Info[ i ].CodePage;
                S = CP.ToString( ) + " - " + Info[ i ].DisplayName;
                int Z=comboBox1.Items.Add( new ComboInfo(S,CP) );
                if ( 65001 == CP )
                {
                    comboBox1.SelectedIndex = Z;
                    CodePage = CP;
                }
            }
        }
        public Form1 ( )
        {
            Decoder = new  icAztecPro(3000,3000);

            InitializeComponent( );
            InitializeCodePages( );

            ModeToForm( );

        }
        #region ModeToForm
        
        private void LabelModeToForm ( )
        {
            switch ( Decoder.LabelMode )
            {
                case AZ_LABEL_MODE.NORMAL: LabelComboBox.SelectedIndex = 0; break;
                default: LabelComboBox.SelectedIndex = 0; break;
            }
        }

        private void SpeedModeToForm ( )
        {
            switch ( Decoder.SpeedMode )
            {
                case AZ_DECODER_SPEED.ROBUST: SpeedComboBox.SelectedIndex = 0; break;
                default: SpeedComboBox.SelectedIndex = 1; break;
            }
        }

        private void CellColorToForm ( )
        {
            switch ( Decoder.CellColor )
            {
                case AZ_CELL_COLOR.BLACKONWHITE: CellColorComboBox.SelectedIndex = 0; break;
                case AZ_CELL_COLOR.WHITEONBLACK: CellColorComboBox.SelectedIndex = 1; break;
                case AZ_CELL_COLOR.ANY: CellColorComboBox.SelectedIndex = 2; break;
            }
        }

        private void QualityModeToForm ( )
        {
            switch ( Decoder.QualityMask )
            {
                case AZ_QUALITY_MASK.NO: QualityComboBox.SelectedIndex = 0; break;
                default: QualityComboBox.SelectedIndex = 1; break;
            }
        }
        private void MaxAZCountToForm ( )
        {
            MaxQRCountEdit.Value = Decoder.MaxAZCount;
        }
        private void FilterModeToForm ( )
        {
//            switch ( Decoder.FilterMode )
//            {
//                case QR_FILTER_MODE.FM_NON:
                    FilterComboBox.SelectedIndex = 0; 
//                    break;
//            }
        }
        private void QzModeToForm()
        {
            switch (Decoder.QzMode)
            {
                case AZ_QZ_MODE.STANDARD: QzComboBox.SelectedIndex = 0; break;
                case AZ_QZ_MODE.SMALL: QzComboBox.SelectedIndex = 1; break;
            }
        }
        private void SymbolTypeModeToForm()
        {
            switch (Decoder.Symbology)
            {
                case AZ_SYMBOL_MODE.NORMAL: SymbologyComboBox.SelectedIndex = 0; break;
                case AZ_SYMBOL_MODE.RUNES: SymbologyComboBox.SelectedIndex = 1; break;
                
            }
        }

//        private void TimeoutToForm ( )
//        {
//            TimeOutEdit.Value = Decoder.Timeout;
//        }

        private void ModeToForm ( )
        {
            MaxAZCountToForm( );
            
            LabelModeToForm( );
            SpeedModeToForm( );
            CellColorToForm( );
            QualityModeToForm( );
            FilterModeToForm( );
            QzModeToForm();
            SymbolTypeModeToForm();
//            TimeoutToForm( );
        }
        #endregion


        #region FormToMode
        
        private void FormToLabelMode ( )
        {
            switch ( LabelComboBox.SelectedIndex )
            {
                case 0: Decoder.LabelMode = AZ_LABEL_MODE.NORMAL; break;
            }
        }

        private void FormToSpeedMode ( )
        {
            switch ( SpeedComboBox.SelectedIndex )
            {
                case 0: Decoder.SpeedMode = (int)0; break;
            }
        }

        private void FormToCellColor ( )
        {
            switch ( CellColorComboBox.SelectedIndex )
            {
                case 0: Decoder.CellColor = AZ_CELL_COLOR.BLACKONWHITE; break;
                case 1: Decoder.CellColor = AZ_CELL_COLOR.WHITEONBLACK; break;
                case 2: Decoder.CellColor = AZ_CELL_COLOR.ANY; break;
            }
        }

        private void FormToQualityMode ( )
        {
            switch (  QualityComboBox.SelectedIndex)
            {
                case 0:Decoder.QualityMask = AZ_QUALITY_MASK.NO; break;
                default: Decoder.QualityMask = AZ_QUALITY_MASK.ALL; break;
            }
        }
        private void FormToMaxQRCount ( )
        {
            Decoder.MaxAZCount = (int)MaxQRCountEdit.Value;
        }

        private void FormToFilterMode ( )
        {
            switch ( FilterComboBox.SelectedIndex) 
            {
                case 0: Decoder.FilterMode = AZ_FILTER_MODE.NON; break;
                case 1: Decoder.FilterMode = AZ_FILTER_MODE.AUTO; break;
            }
        }

        private void FormToQzMode()
        {
            switch (QzComboBox.SelectedIndex)
            {
                case 0: Decoder.QzMode = AZ_QZ_MODE.STANDARD; break;
                case 1: Decoder.QzMode = AZ_QZ_MODE.SMALL; break;
            }
        }

        private void FormToSymbolTypeMode()
        {
            switch (SymbologyComboBox.SelectedIndex)
            {
                case 0: Decoder.Symbology =AZ_SYMBOL_MODE.NORMAL; break;
                case 1: Decoder.Symbology =AZ_SYMBOL_MODE.RUNES; break;
               
            }
        }


//        private void FormToTimeout ( )
//        {
//            Decoder.Timeout = (int)TimeOutEdit.Value;
//        }

        private void FormToMode ( )
        {
            FormToMaxQRCount( );
            
            FormToLabelMode( );
            FormToSpeedMode( );
            FormToCellColor( );
            FormToQualityMode( );
            FormToFilterMode( );
            FormToQzMode( );
            FormToSymbolTypeMode();
//            FormToTimeout( );
        }
        #endregion

        private void Clear ( )
        {
            TimeEdit.Text = "";
            CountEdit.Text = "";
            rrEdit.Text = "";
            SymbolNumber.Enabled = false;
            SymbolNumber.Value = 0;
            SymbolNumber.Maximum = 0;
            FAZ_Info = null;
            //vvvvvvvvvvvvvvvvvvvv
            if (SourcePicture!=null)
              SourcePicture.Dispose();
            //vvvvvvvvvvvvvvvvvvvv
        }
        private void CopyPicture ( )
        {
            Bitmap B = new Bitmap( SourcePicture );
            Rectangle Re = new Rectangle( 0, 0, B.Width, B.Height );
            Picture = B.Clone( Re, PixelFormat.Format24bppRgb );
            Img.Image = Picture;
        }

        private void DrawCorners(bool Ok, PointF[] RowCols)
        {
            if ( Picture == null ) return;
            float X1, X2, Y1, Y2;
            int I1, I2, I;
            Pen P;
            float wid = Picture.Width/600+3;
            if ( Ok )
                P = new Pen( Color.Lime,wid);
            else
                P = new Pen(Color.Red, wid);
            Graphics G = Graphics.FromImage(Picture);
            for ( I = 0; I < 4; I++ )
            {
                I1 = ( I  + 0 );
                I2 = ( I  + 1 );
                if ( I2 > 3 ) I2 = 0;
                X1 = RowCols[ I1 ].X;
                Y1 = RowCols[ I1 ].Y;
                X2 = RowCols[ I2 ].X;
                Y2 = RowCols[ I2].Y;
                if (Math.Abs(X1) > 5000) continue;
                if (Math.Abs(X2) > 5000) continue;
                if (Math.Abs(Y1) > 5000) continue;
                if (Math.Abs(Y2) > 5000) continue;
                G.DrawLine(P, X1, Y1, X2, Y2);
            }

            Img.Image = Picture;
        }


        private void button2_Click (object sender, EventArgs e)
        {
            DateTimeOffset dto;
            int ms = 0;
            int s = 0;
            int h, m;
            String RReason;

            FormToMode();
            button2.Enabled = false;

            dto = DateTimeOffset.Now;
            ms = dto.Millisecond;
            h = dto.Hour;
            m = dto.Minute;
            s = dto.Second;
            
            Decoder.DecodeImage( Picture );

            dto = DateTimeOffset.Now;
            h = dto.Hour - h;
            m = dto.Minute - m;
            s = dto.Second - s;
            ms = dto.Millisecond - ms;

            if (((h * 12 + m) * 60 + s) < 0)
                h = m = s = ms = 0;
            TimeEdit.Text = (((h*12+m)*60+s)*1000+ms).ToString();

            if (Decoder.Rejection_Reason  == AZ_REJECTION_REASONS.AZ_OK)
                rrEdit.Text = "OK";
            else if (Decoder.Rejection_Reason == AZ_REJECTION_REASONS.AZ_DISCONNECTED)
                rrEdit.Text = "Decoder Disconnected";
            else if (Decoder.Rejection_Reason == AZ_REJECTION_REASONS.AZ_Data_RS_Error)
                rrEdit.Text = "Reed Solomon Error";
            else if (Decoder.Rejection_Reason == AZ_REJECTION_REASONS.AZ_CharEncodation_Error)
                rrEdit.Text = "Incorrect Data";
            else
                rrEdit.Text = Decoder.Rejection_Reason.ToString();

            //            rrEdit.Text = Decoder.Rejection_Reasons.ToString( );

            AZCount = Decoder.Count;
            CountEdit.Text = AZCount.ToString( );
            
            if ( AZCount > 0 )
            {
                SymbolNumber.Enabled = true;
                SymbolNumber.Maximum = AZCount - 1;
                ShowInfo(0);
            }

            SymbolNumber.Focus();

        }

        public void ClearForm()
        {
            AZCount = 0;
            TB_SymbologyID.Text = "";
            TB_ActColor.Text = "";
            
            DimTextBox.Text = "";
            RSErrTextBox.Text = "";
           
           
           

//            textBox1.Text = "";
            richTextBox1.Clear();
            TB_symbol_contrast.Text = "";
            TB_axial_nonuniformity.Text = "";
            TB_fixed_pattern_damage.Text = "";
            //TB_QZ_damage.Text = "";
            TB_grid_nonuniformity.Text = "";
            TB_unused_error_correction.Text = "";
            TB_vertical_print_growth.Text = "";
            TB_horizontal_print_growth.Text = "";

            TB_symbol_contrast_grade.Text = "";
            TB_axial_nonuniformity_grade.Text = "";
            TB_grid_nonuniformity_grade.Text = "";
            TB_fixed_pattern_damage_grade.Text = "";
            //TB_QZ_damage_grade.Text = "";
            TB_unused_error_correction_grade.Text = "";
            TB_modulation_grade.Text = "";
            TB_decode_grade.Text = "";
            TB_overall_grade.Text = "";
        }
        private void button1_Click(object sender, EventArgs e)
        {
            ClearForm();
            Clear( );
            DialogResult R = OpenDialog.ShowDialog( );
            if ( R == DialogResult.OK )
            {
                SourcePicture = Image.FromFile( OpenDialog.FileName );
                CopyPicture( );
                LabelFileName.Text = OpenDialog.FileName;
                button2.Enabled = true;
            }

        }

        private void ShowInfo (int Index)
        {
            FAZ_Info = Decoder.Get_AZ_Info( Index );
            CopyPicture( );
            for ( int i = 0; i < Decoder.Count; i++ )
            {
                TAztec_Info iInfo = Decoder.Get_AZ_Info( i );
                PointF[] RC = iInfo.Corners;
                bool Ok = (i==Index) && (iInfo.RSErr>=0);
                DrawCorners( Ok, RC );
            }
            InfoToForm( );
        }
        String QValue (float V)
        {
//            if (V < 0) return "";
            return V.ToString("0.00");
        }
        String QGrade (float V)
        {
            if ( V < 0 ) return " - ";
            return V.ToString(  );
        }
        private void InfoToForm ( )
        {
            if (FAZ_Info == null)
            {
                ClearForm();
            }
            else
            {
                String SymbologyID;
                String[] no_yes = { "No", "Yes" };
                String Clr;

                SymbologyID = "]z0"; //FAZ_Info.GetSymbologyID();
                TB_SymbologyID.Text = SymbologyID;

                //                textBox1.Text = FQR_Info.GetDecodedChars(CodePage);
                richTextBox1.Text = FAZ_Info.GetDecodedString(CodePage);

               

                TB_ActColor.Text = FAZ_Info.ActColor.ToString();
                DimTextBox.Text = FAZ_Info.Dim.ToString();
                RSErrTextBox.Text = FAZ_Info.RSErr.ToString();


                TAZ_Quality Q = FAZ_Info.Quality;

                TB_symbol_contrast.Text = QValue(Q.symbol_contrast);
                TB_axial_nonuniformity.Text = QValue(Q.axial_nonuniformity);
                //                TB_fixed_pattern_damage.Text = QValue( Q.fixed_pattern_damage );
                TB_grid_nonuniformity.Text = QValue(Q.grid_nonuniformity);
                TB_unused_error_correction.Text = QValue(Q.unused_error_correction);
                //   TB_vertical_print_growth.Text = QValue( Q.vertical_print_growth);
                //   TB_horizontal_print_growth.Text = QValue( Q.horizontal_print_growth);

                TB_symbol_contrast_grade.Text = QGrade(Q.symbol_contrast_grade);
                TB_axial_nonuniformity_grade.Text = QGrade(Q.axial_nonuniformity_grade);
                TB_grid_nonuniformity_grade.Text = QGrade(Q.grid_nonuniformity_grade);
                TB_fixed_pattern_damage_grade.Text = QGrade(Q.fixed_pattern_damage_grade);
                TB_unused_error_correction_grade.Text = QGrade(Q.unused_error_correction_grade);
                TB_modulation_grade.Text = QGrade(Q.modulation_grade);
                TB_format_grade.Text = QGrade(-1);
                TB_version_grade.Text = QGrade(-1);
                TB_decode_grade.Text = QGrade(Q.decode_grade);
                TB_overall_grade.Text = QGrade(Q.overall_grade);

            }
            
        }
        private void SymbolNumber_ValueChanged (object sender, EventArgs e)
        {
            int Index = (int)SymbolNumber.Value ;
            ShowInfo( Index );
        }

        private void comboBox1_SelectedIndexChanged (object sender, EventArgs e)
        {
            int Index = comboBox1.SelectedIndex;
            object O = comboBox1.Items[Index];
            if (O is ComboInfo)
                CodePage = (O as ComboInfo).Codepage;
            InfoToForm( );
        }

        private void Img_MouseDown(object sender, MouseEventArgs e)
        {
            int col, row;
            int i, n;
            int i0;
            int s0, s1, s;
            bool confirm;
            int rowcount = Picture.Height;
            int colcount = Picture.Width;
            TAztec_Info iInfo;
            PointF[] RC;

            int r, w, c, h, dw, dh;

            c = e.X;
            r = e.Y;
            w = Img.Width;
            h = Img.Height;

            dw = dh = 0;
            if (rowcount * w  > colcount * h){ //w/h > colcount/rowcount => Vertical stretch
                dw = (w-colcount*h/rowcount)/2;
            }
            else if (rowcount * w  < colcount * h) // horizontal stretch
            {
                dh = (h-rowcount*w/colcount)/2;
            }
            if (dw>0)
//                col = (c - dw) * colcount / (colcount*h/rowcount) ;
                col = (c - dw) * rowcount / h;
            else
                col = c * colcount / w;
            if (dh>0)
                row = (r - dh) * colcount / w;
            else
                row = r * rowcount / h;

            i0 = -1;
            s1 = 0x7FFFFFFF;  
            for (i = 0; i < AZCount; i++)
            {
                iInfo = Decoder.Get_AZ_Info(i);
                RC = iInfo.Corners;
                s0 = (int)((RC[0].Y - row) * (RC[2].X - col) -
                           (RC[0].X - col) * (RC[2].Y - row));
                confirm = true;
                for (n = 1; n < 4; n++)
                {
                    s = (int)((RC[n % 4].Y - row) * (RC[(n + 1) % 4].X - col) -
                        (RC[(n) % 4].X - col) * (RC[(n + 1) % 4].Y - row));
                    if ((s0 > 0) && (s < 0)) confirm = false;
                    if ((s0 < 0) && (s > 0)) confirm = false;
                }
                if (confirm) // point of "mouse down" belongs to rectangle
                {
                    SymbolNumber.Value = i; // change matrix to "i"
                    return;
                }
                for (n = 0; n < 4; n++) // looking for closest corner
                {
                    s = (int)((RC[n].Y - row) * (RC[n].Y - row) +
                              (RC[n].X - col) * (RC[n].X - col));
                    if (s1 > s)
                    {
                        s1 = s;
                        i0 = i;
                    }
                }
            }
            if (i0 >= 0)
            {
                SymbolNumber.Value = i0;
                return;
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

    }
}