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

using LiczbyZespolone;

namespace MandelbrotEksplorator
{
    public partial class Form1 : Form
    {
        Complex min = new Complex(-2.2, -1.2); //min,max - zakres badanej plaszczyzny zespolonej
        Complex max = new Complex(1.2, 1.2);
        const byte N = 255; //ilosc iteracji				
        Bitmap bufor; //bufor

        private Complex ClientToZespolone(int x, int y)
        {
            return min + new Complex(x * (max.Real - min.Real) / ClientSize.Width, y * (max.Imag - min.Imag) / ClientSize.Height);
        }


        public Form1()
        {
            InitializeComponent();
        }

        private void zamknijToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
            Text = "Czekaj...";
            Cursor = Cursors.WaitCursor;

            //bufor = new Bitmap(ClientSize.Width, ClientSize.Height - statusStrip1.Height);
            bufor = new Bitmap(ClientSize.Width, ClientSize.Height);

            for (int x = 0; x < bufor.Width; x++) //x,y - wspolrzedne pikseli
                for (int y = 0; y < bufor.Height; y++)
                {
                    Complex c = 0, z = 0;

                    //Mandelbrot
                    if (zbiórMandelbrotaToolStripMenuItem.Checked)
                    {
                        c = ClientToZespolone(x, y);
                        z = 0;
                    }
                    //Julia
                    if (zbiórJuliiToolStripMenuItem.Checked)
                    {
                        c = new Complex(0.25, 0.55);
                        z = ClientToZespolone(x, y);
                    }

                    byte indeks = 0;
                    for (; indeks < N; indeks++)
                    {
                        z = z * z + c;
                        if (z.Norm >= 4) break;
                    }
                    if (indeks == N)
                        bufor.SetPixel(x, y, Color.Black);
                    else
                        //bufor.SetPixel(x,y,Color.White);
                        bufor.SetPixel(x, y, Color.FromArgb(255 - indeks, 255 - indeks, 255));
                }

            Graphics g = e.Graphics;
            g.DrawImage(bufor, 0, 0);

            //osie
            int x0 = (int)(-min.Real * ClientSize.Width / (max.Real - min.Real));
            int y0 = (int)(-min.Imag * ClientSize.Height / (max.Imag - min.Imag));
            g.DrawLine(new Pen(Color.Gray, 1), new Point(x0, 0), new Point(x0, ClientSize.Height));
            g.DrawLine(new Pen(Color.Gray, 1), new Point(0, y0), new Point(ClientSize.Width, y0));

            if (zbiórMandelbrotaToolStripMenuItem.Checked) Text = "Zbiór Mandelbrota";
            if (zbiórJuliiToolStripMenuItem.Checked) Text = "Zbiór Julii";
            Text += " (zakres od " + min.ToStringI() + " do " + max.ToStringI() + ")";
            Cursor = Cursors.Arrow;
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            Refresh();
        }

        private void zbiórMandelbrotaToolStripMenuItem_Click(object sender, EventArgs e)
        {
            zbiórMandelbrotaToolStripMenuItem.Checked = (sender == zbiórMandelbrotaToolStripMenuItem);
            zbiórJuliiToolStripMenuItem.Checked = (sender == zbiórJuliiToolStripMenuItem);
            Refresh();
        }

        private void Form1_MouseDown(object sender, MouseEventArgs e)
        {
            Complex z = ClientToZespolone(e.X, e.Y);
            Complex rozmiar = max - min;

            switch (e.Button)
            {
                case MouseButtons.Left:
                    rozmiar /= 3;
                    break;
                case MouseButtons.Right:
                    rozmiar *= 3;
                    break;
            }

            min = z - rozmiar / 2;
            max = min + rozmiar;
            Refresh();
        }

        private void Form1_MouseMove(object sender, MouseEventArgs e)
        {
            Complex z = ClientToZespolone(e.X, e.Y);
            toolStripStatusLabel1.Text = "Re: " + z.Real.ToString("G10") + "  Im: " + z.Imag.ToString("G10");
        }

        private void toolStripMenuItem2_Click(object sender, EventArgs e)
        {
            min = new Complex(-2.2, -1.2); //min,max - zakres badanej plaszczyzny zespolonej
            max = new Complex(1.2, 1.2);
            Refresh();
        }
    }
}
