package xyz.marsavic.gfxlab.playground.colorfunctions;

import xyz.marsavic.geometry.Vector;
import xyz.marsavic.gfxlab.Color;
import xyz.marsavic.gfxlab.ColorFunctionT;
import xyz.marsavic.gfxlab.elements.Element;
import xyz.marsavic.utils.Defaults;
import xyz.marsavic.utils.Numeric;


public class Planes extends Element implements ColorFunctionT {

	double speed = 5;

	private double distance(double t) {
		return speed * t;
	}

	double ballSpace = 0.8;
	FakeBall [] balls;

	public static final Defaults<Planes> $ = Defaults.args();

	private class FakeBall {
		Color c = Color.rgb(Math.random(), Math.random(), Math.random());
		double r = Math.random()/4+0.25;
		double xOffset;

		double maxHeight = Math.random()/2;
		double minHeight = -Math.random()/2;
		double phaseOffset = Math.random();

		public FakeBall(int offset) {
			this.xOffset = offset*ballSpace + Math.random()/5;
		}

		public double currentHeight(double t) {
			return (Numeric.sinT(distance(t)+phaseOffset)+1)*(maxHeight-minHeight)/2+minHeight;
		}

		public Vector center(double t) {
			return Vector.xy(xOffset+distance(t), currentHeight(t));
		}
	}

	public Planes() {
		int ballNum = 20;

		balls = new FakeBall[ballNum];
		for (int i = 0; i < ballNum; i++) {
			balls[i] = new FakeBall(i-ballNum/2);
		}

	}
	ColorFunctionT ceil = new Blobs(5, 3.5, 0.2), floor = new BoringGrid();
	
	@Override
	public Color at(double t, Vector p) {
		for (FakeBall ball : balls) {
			double distanceFromCenterSq = p.sub(ball.center(t)).length(),
					rSqr = ball.r * ball.r;
			if (distanceFromCenterSq < rSqr) {
				return ball.c.mul((rSqr - distanceFromCenterSq) / rSqr);
			}
		}

		double infinity = 0.15;
		if (p.y() > infinity) {
			return ceil.at(t, Vector.xy(p.x()/(p.y()-infinity)-distance(t),
					(1-p.y())/(p.y()-infinity)));
		}
		if (p.y() < -infinity) {
			return floor.at(t, Vector.xy(p.x()/(-infinity-p.y())-distance(t),
					(p.y()-(-1))/(-infinity-p.y())));
		}

		return Color.BLACK;
	}
	
}
