/*
 * The MIT License
 *
 * Copyright 2013 Masahiko, SAWAI <masahiko.sawai@gmail.com>.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.example.hello.android.view_custom_drawing_animation;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Random;

/**
 *
 * @author sawai
 */
public class LineArt implements Serializable
{

	public static final Random RANDOM = new Random();
	public static final int NUMBER_OF_LINES = 20;
	public static final float SCREEN_WIDTH = 100.0f;
	public static final float SCREEN_HEGHT = 100.0f;
	public static final int MAX_SPEED = 2;
	private int numberOfLines;
	private Line lines[];
	private int colors[];
	private int currentIndex;
	private PointMover mover1, mover2;
	private PointColorChanger pointColor;

	public LineArt(int numberOfLines)
	{
		this.numberOfLines = numberOfLines;
		this.lines = new Line[numberOfLines];
		for (int i = 0; i < numberOfLines; i++)
		{
			this.lines[i] = new Line(0, 0, 0, 0);
		}
		this.colors = new int[numberOfLines];
		Arrays.fill(colors, Color.TRANSPARENT);
		this.currentIndex = 0;
		float x, y, dx, dy;
		x = RANDOM.nextFloat() * SCREEN_WIDTH;
		y = RANDOM.nextFloat() * SCREEN_HEGHT;
		dx = RANDOM.nextFloat() / 2.0f + 0.5f;
		dx *= RANDOM.nextBoolean() ? MAX_SPEED : -MAX_SPEED;
		dy = RANDOM.nextFloat() / 2.0f + 0.5f;
		dy *= RANDOM.nextBoolean() ? MAX_SPEED : -MAX_SPEED;
		mover1 = new PointMover(x, y, dx, dy);

		x = RANDOM.nextFloat() * SCREEN_WIDTH;
		y = RANDOM.nextFloat() * SCREEN_HEGHT;
		dx = RANDOM.nextFloat();
		dx *= RANDOM.nextBoolean() ? MAX_SPEED : -MAX_SPEED;
		dy = RANDOM.nextFloat();
		dy *= RANDOM.nextBoolean() ? MAX_SPEED : -MAX_SPEED;
		mover2 = new PointMover(x, y, dx, dy);

		pointColor = new PointColorChanger();
	}

	public LineArt()
	{
		this(NUMBER_OF_LINES);
	}

	public void update()
	{
		mover1.update();
		mover2.update();
		pointColor.update();

		lines[currentIndex].p1.set(mover1.p);
		lines[currentIndex].p2.set(mover2.p);
		colors[currentIndex] = pointColor.toColor();
		currentIndex = (currentIndex + 1) % numberOfLines;
	}

	public void draw(Canvas canvas)
	{
		Paint bg = new Paint();
		bg.setColor(Color.BLACK);
		bg.setStyle(Paint.Style.FILL);
		Paint fg = new Paint();
		fg.setColor(Color.WHITE);

		float scaleX = (float) canvas.getWidth() / SCREEN_WIDTH;
		float scaleY = (float) canvas.getHeight() / SCREEN_HEGHT;
		canvas.save();
		canvas.scale(scaleX, scaleY);
		canvas.drawRect(0, 0, SCREEN_WIDTH, SCREEN_HEGHT, bg);
		for (int i = 0; i < numberOfLines; i++)
		{
			Line line = lines[i];
			int color = colors[i];
			fg.setColor(color);
			canvas.drawLine(line.p1.x, line.p1.y, line.p2.x, line.p2.y, fg);
		}
		canvas.restore();
	}

	class Point implements Serializable
	{

		float x;
		float y;

		public Point(float x, float y)
		{
			this.x = x;
			this.y = y;
		}

		public void set(Point p)
		{
			x = p.x;
			y = p.y;
		}
	}

	class Line implements Serializable
	{

		Point p1;
		Point p2;

		public Line(int x1, int y1, int x2, int y2)
		{
			this.p1 = new Point(x1, y1);
			this.p2 = new Point(x2, y2);
		}
	}

	class PointMover implements Serializable
	{

		Point p;
		float dx, dy;

		public PointMover(float x, float y, float dx, float dy)
		{
			p = new Point(x, y);
			this.dx = dx;
			this.dy = dy;
		}

		public void update()
		{
			p.x += dx;
			if (p.x < 0)
			{
				p.x = -p.x;
				dx = -dx;
			}
			else if (p.x > SCREEN_WIDTH)
			{
				p.x = SCREEN_WIDTH * 2 - p.x;
				dx = -dx;
			}
			p.y += dy;
			if (p.y < 0)
			{
				p.y = -p.y;
				dy = -dy;
			}
			else if (p.y > SCREEN_HEGHT)
			{
				p.y = SCREEN_HEGHT * 2 - p.y;
				dy = -dy;
			}
		}
	}

	class PointColorChanger implements Serializable
	{

		static final int MAX_SPEED = 5;
		static final int MAX_VALUE = 0xff;
		static final int MIN_VALUE = 0x7f;
		int r, g, b;
		int dr, dg, db;

		public PointColorChanger()
		{
			this.r = RANDOM.nextInt(256);
			this.g = RANDOM.nextInt(256);
			this.b = RANDOM.nextInt(256);
			this.dr = RANDOM.nextInt(MAX_SPEED) + 1;
			this.dr *= RANDOM.nextBoolean() ? 1 : -1;
			this.dg = RANDOM.nextInt(MAX_SPEED) + 1;
			this.dg *= RANDOM.nextBoolean() ? 1 : -1;
			this.db = RANDOM.nextInt(MAX_SPEED) + 1;
			this.db *= RANDOM.nextBoolean() ? 1 : -1;
		}

		public void update()
		{
			r += dr;
			if (r < MIN_VALUE)
			{
				r = MIN_VALUE;
				dr = -dr;
			}
			else if (r > MAX_VALUE)
			{
				r = MAX_VALUE;
				dr = -dr;
			}

			g += dg;
			if (g <= MIN_VALUE)
			{
				g = MIN_VALUE;
				dg = -dg;
			}
			else if (g > MAX_VALUE)
			{
				g = MAX_VALUE;
				dg = -dg;
			}

			b += db;
			if (b <= MIN_VALUE)
			{
				b = MIN_VALUE;
				db = -db;
			}
			else if (b > MAX_VALUE)
			{
				b = MAX_VALUE;
				db = -db;
			}
		}

		public int toColor()
		{
			return Color.rgb(r, g, b);
		}
	}
}
