using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace Ball
{
    class clBall
    {
        private byte[,] brgPixelsB;
        private byte[,] brgPixelsG;
        private byte[,] brgPixelsR;
        private byte[,] brgPixelsL;
        private int[,] virgPoints;
        private int[] viLength;
        private int viI;
        private int viJ;


        private int pointMittingX = 0;
        private int viLengthP = 0;
        private double koefX = 0;
        private double koefY = 0;
        private int viFromX = 0;
        private int viFromY = 0;
        private int viTo1 = 0;           
        
     
        private int radius;
        private Form1 myForm;
        private bool fBlock = false;
       
       
        private int viWidth = 0;
        private int viHeight = 0;
        public Graphics graphWork = null;
       
        public Graphics graph = null;
        private byte[] bmpBytesSource;
        private byte[] bmpBytesFore;
        
        //Исходная в половину 
        private static Bitmap bmpStart = null;
        private Bitmap bitmapWorkFore { get; set; }        
        private Bitmap bitmapWork { get; set; }
        

        public clBall(Form1 form1)
        {
            // TODO: Complete member initialization
            myForm = form1;
        }

        internal void vNewSize()
        {
            
            if (fBlock) return;
            fBlock = true;
            
            
            //Адрес картинки            
            string s = myForm.srgFiles[myForm.viImage];
            //Картинка из памяти 
            Bitmap bmpTemp = new Bitmap(s);
            viWidth = bmpTemp.Width;
            viHeight = bmpTemp.Height;
            while (viWidth % 2 != 0)
            {
                viWidth--;
            }
            while (viHeight % 2 != 0)
            {
                viHeight--;
            }
            bmpStart = new Bitmap(viWidth, viHeight);
            graphWork = Graphics.FromImage(bmpStart);
            graphWork.DrawImage(bmpTemp, new Rectangle(0, 0, viWidth, viHeight), 0, 0, bmpTemp.Width, bmpTemp.Height, GraphicsUnit.Pixel);
            graphWork.Dispose();
            //Освобождаем картинку, держущую память  
            bmpTemp.Dispose();
            bmpBytesSource = new Byte[viWidth * viHeight * 4];
            BitmapData bmpTempDataStart = bmpStart.LockBits(new Rectangle(0, 0, viWidth, viHeight), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb);
            unsafe
            {

                try
                {

                    Marshal.Copy(bmpTempDataStart.Scan0, bmpBytesSource, 0, viWidth * viHeight * 4);

                }
                catch (Exception)
                {
                }
                finally
                {
                    bmpStart.UnlockBits(bmpTempDataStart);
                    bmpTempDataStart = null;

                }
            }

            brgPixelsB = new byte[viWidth, viHeight];
            brgPixelsG = new byte[viWidth, viHeight];
            brgPixelsR = new byte[viWidth, viHeight];
            brgPixelsL = new byte[viWidth, viHeight];

            //Забираем в массивы все биты источника 
            for (int i = 0; i < viWidth; i++)
            {
                for (int j = 0; j < viHeight; j++)
                {
                    brgPixelsB[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4)];
                    brgPixelsG[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 1];
                    brgPixelsR[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 2];
                    brgPixelsL[i, j] = bmpBytesSource[i * 4 + (j * viWidth * 4) + 3];


                }
            }
            double dRadBall = (double)bmpStart.Height / Math.PI;
            radius = (int)dRadBall;

            bitmapWork = new Bitmap(2 * radius, 2 * radius);
            graphWork = Graphics.FromImage(bitmapWork);
            Color cl;            
            virgPoints = new int[radius, radius];
            viLength = new int[radius];
            int[] viLength1 = new int[radius];
            double c=0;
            for (int m = 0; m < radius; m++)
            {

                viLength1[m] = (int)(4 * ((Math.PI * m * radius) + (radius - m) * (radius - m)) / (radius + m));
                viLength[m] = (int)(Math.PI*( 3 *( m + radius )-(int)Math.Sqrt((3*m+radius)+(3*radius +m))));   
                c = (3 * (radius - m) * (radius - m)) / ((radius + m) * (radius + m));
                viLength[m] = (int)(Math.PI * (m + radius) * (1 + c / (10 + Math.Sqrt(4 - c))));

                if (viLength[m] < viLength1[m]) viLength[m] = viLength1[m];


                viLength[m] = (int)Math.Round(((double)viLength[m] / (double)4),0);
            }
            

            for (int m = 0; m < radius; m++)
            {
                    graphWork.DrawEllipse(new Pen(Color.FromArgb(255, 0, 0), 1), radius - m, 0, 2 * m, 2 * radius);
                    for (int j = 0; j < bitmapWork.Height / 2; j++)
                    {
                        for (int i = 0; i < bitmapWork.Width; i++)
                        {
                            cl = bitmapWork.GetPixel(i, j);
                            if (cl.R == 255)
                            {

                                if (i <= bitmapWork.Width  / 2)
                                {
                                    virgPoints[m, j] = i;                                  
                                }
                                break;
                            }
                        }
                    }
                
            }

            myForm.WindowState = System.Windows.Forms.FormWindowState.Normal;
            myForm.Width = bmpStart.Width;
            myForm.Height = bmpStart.Height + 200;
            myForm.Left = (myForm.screen.Width - myForm.Width) / 2;
            myForm.Top = (myForm.screen.Height - myForm.Height) / 2;

            myForm.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.CenterImage;
            
         
          



            
            viI = 0;
            viJ = 0;
            fBlock = false;
        }

        internal void LineTick()
        {            
            if (fBlock) return;
            fBlock = true;
            graphWork.Clear(Color.FromArgb(0, 0, 0, 0));
            bmpBytesFore = new byte[2 * radius * 2 * radius * 4];
            //Двигаемся по увеличению радиуса хранящегося по дугам (, начала дуг слева направо  в virgPoints
            for (int R = 0; R < radius; R++)
            {
                //длина дуги для радиуса 
                viLengthP = viLength[R];
                //Соотношение с исходным радиусом четвертушки дуги - НА СКОЛЬКО БОЛЬШЕ 
                koefX = (double)viLengthP / (double)radius;
                //
                koefY = viHeight / (double)2 / (double)radius;

                //Пойдём вниз, от 0  c радиусом R 
                for (int j = 0; j < radius; j++)
                {
                    //Точуа встречи слева направо для данного R
                    pointMittingX = virgPoints[R, j];
                    //Ищем сохранённую точку счтречи слева направа 
                    for (int i = 0; i <= radius; i++)
                    {
                        //Достигли точки встречи 
                        if (i >= pointMittingX)
                        {
                            //Куда в массиве - это точка i j
                            viTo1 = j * (2 * radius) * 4 + i * 4;
                            //Откуда 
                            viFromX = viHeight / 2 - ((int)((double)radius * koefX) - (int)(i * koefX));
                            //viFromX = viHeight/2  - (int)(i * koefX);
                            //if (viFromX < 0) viFromX = 0;
                            viFromY = (int)((double)j * (double)koefY);
                            //myForm.Text=viFromX.ToString();


                            try
                            {
                                viFromX = (viFromX + viI) % viWidth;
                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];


                                //viTo1 = (j+1)* (2 * radius) * 4 - i * 4;
                                viTo1 = (j + 1) * (2 * radius) * 4 - i * 4;
                                viFromX = viHeight / 2 + ((int)((double)radius * koefX) - (int)(i * koefX));
                                viFromX = (viFromX + viI) % viWidth;
                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];



                                viTo1 = 2 * radius * 2 * radius * 4 - (2 * radius) * 4 - j * (2 * radius) * 4 + i * 4;
                                //viFromX = viHeight  + ((int)((double)radius * koefX) + (int)(i * koefX));
                                //viFromX = (viHeight - 1) - ((int)((double)radius * koefX) + (int)(i * koefX));
                                viFromX = viHeight / 2 - ((int)((double)radius * koefX) - (int)(i * koefX));
                                viFromX = (viFromX + viI) % viWidth;
                                //Работает со сдвигом 
                                //viFromY = (int)((double)(viHeight-1-j) / (double)koefY);
                                viFromY = viHeight - 1 - (int)((double)j * (double)koefY);
                                //viFromY = viFromY % 300;


                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];


                                //viTo1 =  j * (2 * radius) * 4 + i * 4;

                                viTo1 = 2 * radius * 2 * radius * 4 - j * (2 * radius) * 4 - i * 4;
                                //if (viFromM < viTo1) viFromM = viTo1;
                                //myForm.Text = viFromM.ToString();
                                viFromX = viHeight / 2 + ((int)((double)radius * koefX) - (int)(i * koefX));
                                viFromX = (viFromX + viI) % viWidth;


                                bmpBytesFore[viTo1] = brgPixelsB[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 1] = brgPixelsG[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 2] = brgPixelsR[viFromX, viFromY];
                                bmpBytesFore[viTo1 + 3] = brgPixelsL[viFromX, viFromY];


                            }
                            catch (Exception ex)
                            {
                                myForm.Text = ex.Message;
                            }
                            break;
                        }


                    }





                }


            }
            //for (int i = 0; i < 2 * radius; i++)
            //{
            //    for (int j = 0; j < 2 * radius; j++)
            //    {
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4] = brgPixelsB[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 1] = brgPixelsG[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 2] = brgPixelsR[i, j];
            //        bmpBytesFore[j * (2 * radius) * 4 + i * 4 + 3] = brgPixelsL[i, j];
            //    }
            //}




            BitmapData bitmapData = bitmapWork.LockBits(new Rectangle(0, 0, bitmapWork.Width, bitmapWork.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppRgb);
            unsafe
            {
                Marshal.Copy(bmpBytesFore, 0, bitmapData.Scan0, bmpBytesFore.Length);

            }
            bitmapWork.UnlockBits(bitmapData);

            myForm.pictureBox1.Image = bitmapWork;

            viI+=2;

            fBlock = false;
        }
    }
}
