package math;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;

import math.number.NumberComplex;
import stdlib.Color;
import stdlib.Picture;

/**
 * Plots the size-by-size region of the Mandelbrot set, centered on (xc, yc).
 * @author Daniel Weschke
 */
public class Set {

    /**
     * @param z0
     * @param max
     * @return number of iterations to check if c = a + ib is in Mandelbrot set
     */
    public int mand(NumberComplex z0, int max) {
    	int i;
    	NumberComplex z = z0;
        for(i=0; i<max; i++){
            if(z.mod() > 2.0) return i;
            z = z.times(z).plus(z0);
        }
        return max;
    }
    
    /**
     * @param c
     * @param z
     * @param ITERS
     * @return number of iterations to check z is in the Julia set of c
     */
    int julia(NumberComplex c, NumberComplex z, int max) {
    	int i;
        for(i=0; i<max; i++) {
            if(z.mod() > 2.0) return i;
            z = z.times(z).plus(c);
        }
        return max - 1;
    }
    
    public void mandelbrot(double xc, double yc, double size){
        int n   = 512;   // create N-by-N image
        int max = 255;   // maximum number of iterations
        int i, j;

        double x0, y0;
        NumberComplex z0;
        int gray;
        Color color;
        Picture pic = new Picture(n, n);
        for(i=0; i<n; i++){
            for(j=0; j<n; j++){
                x0 = xc - size/2 + size*i/n;
                y0 = yc - size/2 + size*j/n;
                z0 = new NumberComplex(x0, y0);
                gray = max - mand(z0, max);
                color = new Color(gray, gray, gray);
                pic.set(i, n-1-j, color);
            }
        }
        pic.show();
    }
    
    public void mandelbrotColor(double xc, double yc, double size) throws FileNotFoundException{
        int n = 512;
        int ITERS = 256;
        int i, j, k;
        // read in color map
        int r, g, b;
        Color[] colors = new Color[ITERS];
		Scanner in = new Scanner(new File("resources/mandel.txt"));
        for(k=0; k<ITERS; k++) {
            r = in.nextInt();
            g = in.nextInt();
            b = in.nextInt();
            colors[k] = new Color(r, g, b);
        }
        in.close();
        // compute Mandelbrot set
        Picture pic = new Picture(n, n);
        double x, y;
        NumberComplex z0;
        for(i=0; i<n; i++) {
            for(j=0; j<n; j++) {
                x = xc - size/2 + size*i/n;
                y = yc - size/2 + size*j/n;
                z0 = new NumberComplex(x, y);
                k = mand(z0, ITERS - 1);
                pic.set(i, n-1-j, colors[k]);
            }
        }
        pic.show();
    }

    public void juliaColor(double re, double im) throws FileNotFoundException {
        NumberComplex c = new NumberComplex(re, im);
        juliaColor(c);
    }
    
    /**
     * @param c
     * @throws FileNotFoundException
     * @see <a href="http://www.jimloy.com/fractals/julia.htm">http://www.jimloy.com/fractals/julia.htm</a>
     */
    public void juliaColor(NumberComplex c) throws FileNotFoundException {
        int n = 512;
        int ITERS  = 256;
        
        int i, j, k;
        
        double xmin   = -2.0;
        double ymin   = -2.0;
        double width  =  4.0;
        double height =  4.0;

        // read in color map
        int r, g, b;
        Color[] colors = new Color[ITERS];
		Scanner in = new Scanner(new File("resources/mandel.txt"));
        for(k=0; k<ITERS; k++) {
            r = in.nextInt();
            g = in.nextInt();
            b = in.nextInt();
            colors[k] = new Color(r, g, b);
        }
        in.close();
        Picture pic = new Picture(n, n);

        double x, y;
        NumberComplex z;
        for(i=0; i<n; i++){
            for(j=0; j<n; j++) {
                x = xmin + i*width/n;
                y = ymin + j*height/n;
                z = new NumberComplex(x, y);
                k = julia(c, z, ITERS);
                pic.set(i, j, colors[k]);
            }
        }
        pic.show();
    }

    public static void main(String[] args) throws FileNotFoundException  {
    	Set set = new Set();
//    	set.mandelbrot(-.5, 0, 2);
//    	set.mandelbrot(.1015, -.633, 1);
//    	set.mandelbrot(.1015, -.633, 0.1);
//    	set.mandelbrot(.1015, -.633, 0.01);
//    	set.mandelbrot(.1015, -.633, 0.001);

//    	set.mandelbrotColor(-.5, 0, 2);
    	// increase dwell
//    	set.mandelbrotColor(-0.7615134027775, 0.0794865972225, 0.0032285925920);
    	
//    	set.juliaColor(-0.75, 0.1);
//    	set.juliaColor(-1.25, 0);
//    	set.juliaColor(0.1, 0.7);
//    	set.juliaColor(0.3, -0.6);
//    	set.juliaColor(-.123, .745); // Douady's Rabbit Fractal or the Dragon Fractal
//    	set.juliaColor(-.75, 0); // San Marco Fractal
    	set.juliaColor(-0.391,-0.587); // Siegel Disk Fractal
    }
}
