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 icQRDecNetPro;

namespace Sharp_QR_EP
{
    public partial class Form1 : Form
    {
        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 ic_Decoder_Pro Decoder; 
        private TQR_Info FQR_Info=null;
        int QRCount;

        private void InitializeCodePages ( )
        {
            Info = Encoding.GetEncodings( );
            int j;
            for ( int i = 0; i < Info.Length; i++ )
            {
                String S;
                Encoding E = Encoding.UTF8;// Console.Out.Encoding;
                int CP = Info[ i ].CodePage;
                S = CP.ToString( ) + " - " + Info[ i ].DisplayName;
                j = comboBox1.Items.Add(S);
                if ( E.CodePage == CP )
                {
                    comboBox1.SelectedIndex = j;
                    CodePage = CP;
                }
            }
        }
        public Form1 (IntPtr  decptr )
        {
            Decoder = new ic_Decoder_Pro(decptr);

            InitializeComponent( );
            InitializeCodePages( );

            ModeToForm( );

        }
        #region ModeToForm
        private void MirrorModeToForm ( )
        {
            switch ( Decoder.MirrorMode )
            {
                case QR_MIRROR_MODE.MM_NORMAL: MirrorComboBox.SelectedIndex = 0; break;
                case QR_MIRROR_MODE.MM_MIRROR: MirrorComboBox.SelectedIndex = 1; break;
                case QR_MIRROR_MODE.MM_ANY: MirrorComboBox.SelectedIndex = 2; break;
            }
        }
        private void LabelModeToForm ( )
        {
            switch ( Decoder.LabelMode )
            {
                case QR_LABEL_MODE.LM_STANDARD: LabelComboBox.SelectedIndex = 0; break;
                default: LabelComboBox.SelectedIndex = 0; break;
            }
        }

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

        private void CellColorToForm ( )
        {
            switch ( Decoder.CellColor )
            {
                case QRCELL_COLOR.QRCL_BLACKONWHITE: CellColorComboBox.SelectedIndex = 0; break;
                case QRCELL_COLOR.QRCL_WHITEONBLACK: CellColorComboBox.SelectedIndex = 1; break;
                case QRCELL_COLOR.QRCL_ANY: CellColorComboBox.SelectedIndex = 2; break;
            }
        }

        private void QualityModeToForm ( )
        {
            switch ( Decoder.QualityMask )
            {
                case QR_QUALITY_MASK.QR_QM_NO: QualityComboBox.SelectedIndex = 0; break;
                default: QualityComboBox.SelectedIndex = 1; break;
            }
        }
        private void MaxQRCountToForm ( )
        {
            MaxQRCountEdit.Value = Decoder.MaxQRCount;
        }
        private void FilterModeToForm ( )
        {
//            switch ( Decoder.FilterMode )
//            {
//                case QR_FILTER_MODE.FM_NON:
                    FilterComboBox.SelectedIndex = 0; 
//                    break;
//            }
        }
        private void QzModeToForm()
        {
            switch (Decoder.QzMode)
            {
                case (int)QRQZ_MODE.QRQZ_STANDARD: QzComboBox.SelectedIndex = 0; break;
                case (int)QRQZ_MODE.QRQZ_SMALL: QzComboBox.SelectedIndex = 1; break;
            }
        }
        private void SymbolTypeModeToForm()
        {
            switch (Decoder.Symbology)
            {
                case (int)QRSYMBOL_MODE.QRC_NORMAL: SymbologyComboBox.SelectedIndex = 0; break;
                case (int)QRSYMBOL_MODE.QRC_MICRO : SymbologyComboBox.SelectedIndex = 1; break;
                case (int)QRSYMBOL_MODE.QRC_ANY   : SymbologyComboBox.SelectedIndex = 2; break;
            }
        }

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

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


        #region FormToMode
        private void FormToMirrorMode ( )
        {
            switch ( MirrorComboBox.SelectedIndex )
            {
                case 0: Decoder.MirrorMode = QR_MIRROR_MODE.MM_NORMAL; break;
                case 1: Decoder.MirrorMode = QR_MIRROR_MODE.MM_MIRROR; break;
                case 2: Decoder.MirrorMode = QR_MIRROR_MODE.MM_ANY; break;
            }
        }
        private void FormToLabelMode ( )
        {
            switch ( LabelComboBox.SelectedIndex )
            {
                case 0: Decoder.LabelMode = QR_LABEL_MODE.LM_STANDARD; break;
            }
        }

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

        private void FormToCellColor ( )
        {
            switch ( CellColorComboBox.SelectedIndex )
            {
                case 0: Decoder.CellColor = QRCELL_COLOR.QRCL_BLACKONWHITE; break;
                case 1: Decoder.CellColor = QRCELL_COLOR.QRCL_WHITEONBLACK; break;
                case 2: Decoder.CellColor = QRCELL_COLOR.QRCL_ANY; break;
            }
        }

        private void FormToQualityMode ( )
        {
            switch (  QualityComboBox.SelectedIndex)
            {
                case 0:Decoder.QualityMask = QR_QUALITY_MASK.QR_QM_NO; break;
                default: Decoder.QualityMask = QR_QUALITY_MASK.QR_QM_ALL; break;
            }
        }
        private void FormToMaxQRCount ( )
        {
            Decoder.MaxQRCount = (int)MaxQRCountEdit.Value;
        }

        private void FormToFilterMode ( )
        {
            switch ( FilterComboBox.SelectedIndex) 
            {
                case 0: Decoder.FilterMode = QR_FILTER_MODE.FM_NON; break;
                case 1: Decoder.FilterMode = QR_FILTER_MODE.FM_AUTO; break;
                case 2: Decoder.FilterMode = QR_FILTER_MODE.FM_DOT_PEEN_TO_NORMAL; break;
         }
        }

        private void FormToQzMode()
        {
            switch (QzComboBox.SelectedIndex)
            {
                case 0: Decoder.QzMode = (int)QRQZ_MODE.QRQZ_STANDARD; break;
                case 1: Decoder.QzMode = (int)QRQZ_MODE.QRQZ_SMALL; break;
            }
        }

        private void FormToSymbolTypeMode()
        {
            switch (SymbologyComboBox.SelectedIndex)
            {
                case 0: Decoder.Symbology =(int)QRSYMBOL_MODE.QRC_NORMAL; break;
                case 1: Decoder.Symbology =(int)QRSYMBOL_MODE.QRC_MICRO; break;
                case 2: Decoder.Symbology =(int)QRSYMBOL_MODE.QRC_ANY; break;
            }
        }


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

        private void FormToMode ( )
        {
            FormToMaxQRCount( );
            FormToMirrorMode( );
            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;
            FQR_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, TRowCols 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 * 2 + 0 );
                I2 = ( I * 2 + 2 );
                if ( I2 > 7 ) I2 = 0;
                X1 = (float)RowCols[ I1 + 1 ];
                Y1 = (float)RowCols[ I1 + 0 ];
                X2 = (float)RowCols[ I2 + 1 ];
                Y2 = (float)RowCols[ I2 + 0 ];
                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_Reasons.ToString() == "QR_SUCCESSFUL")
                rrEdit.Text = "OK";
            else if (Decoder.Rejection_Reasons.ToString() == "QR_RR_DISCONNECTED")
                rrEdit.Text = "Decoder Disconnected";
            else if (Decoder.Rejection_Reasons.ToString() == "QR_ERROR_OF_RS_CODE")
                rrEdit.Text = "Reed Solomon Error";
            else if (Decoder.Rejection_Reasons.ToString() == "QR_POOR_IMAGE_QUALITY")
                rrEdit.Text = "Poor Image Quality";
            else if (Decoder.Rejection_Reasons.ToString() == "QR_ERR_DECODE")
                rrEdit.Text = "Incorrect Data";
            else 
                rrEdit.Text = "QRC not Found";

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

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

            SymbolNumber.Focus();

        }

        public void ClearForm()
        {
            QRCount = 0;
            TB_SymbologyID.Text = "";
            TB_ActColor.Text = "";
            MirroredTextBox.Text = "";
            DimTextBox.Text = "";
            RSErrTextBox.Text = "";
            TB_Version.Text = "";
            TB_Level.Text = "";
            TB_Mask.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)
        {
            FQR_Info = Decoder.Get_QR_Info( Index );
            CopyPicture( );
            for ( int i = 0; i < Decoder.QRCount; i++ )
            {
                TQR_Info iInfo = Decoder.Get_QR_Info( i );
                TRowCols RC = iInfo.RowCols;
                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 ( FQR_Info == null )
            {
                ClearForm();
            }
            else
            {
                String SymbologyID;
                String[] no_yes = { "No", "Yes" };
                String Clr;

                SymbologyID = FQR_Info.GetSymbologyID();
                TB_SymbologyID.Text = SymbologyID;

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

                MirroredTextBox.Text = no_yes[Convert.ToInt32(FQR_Info.Mirrored)]; //.ToString( );
                if (FQR_Info.ActColor == 1) Clr = "Black";
                else                        Clr = "White";
                TB_ActColor.Text = Clr;
                DimTextBox.Text = FQR_Info.Dim.ToString( );
                RSErrTextBox.Text = FQR_Info.RSErr.ToString( );
                TB_Version.Text = FQR_Info.Version.ToString();
                TB_Level.Text = FQR_Info.level.ToString();
                TB_Mask.Text = FQR_Info.Mask.ToString();

                TQR_Quality Q = FQR_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(Q.format_grade);
                TB_version_grade.Text    = QGrade(Q.version_grade);
                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;
            CodePage = Info[ Index ].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;
            TQR_Info iInfo;
            TRowCols 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 < QRCount; i++)
            {
                iInfo = Decoder.Get_QR_Info(i);
                RC = iInfo.RowCols;
                s0 = (int)((RC[0] - row) * (RC[3] - col) -
                           (RC[1] - col) * (RC[2] - row));
                confirm = true;
                for (n = 1; n < 4; n++)
                {
                    s = (int)((RC[2 * n % 8] - row) * (RC[(2 * n + 3) % 8] - col) -
                        (RC[(2 * n + 1) % 8] - col) * (RC[(2 * n + 2) % 8] - 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[2 * n] - row) * (RC[2 * n] - row) +
                              (RC[2 * n + 1] - col) * (RC[2 * n + 1] - col));
                    if (s1 > s)
                    {
                        s1 = s;
                        i0 = i;
                    }
                }
            }
            if (i0 >= 0)
            {
                SymbolNumber.Value = i0;
                return;
            }
        }

    }
}