//
// MoonPhase.java:
// Calculate the phase of the moon.
//    Copyright 2014 by Audrius Meskauskas
// You may use or distribute this code under the terms of the GPLv3
//
package akk.astro.droid.moonphase;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;

public class MoonView extends View {
	public static final int moonColor = Color.WHITE;
	public static final int earthshineColor = Color.rgb(20,20,40);
	
	private final Paint paint = new Paint();
	private final MoonPhase moon = new MoonPhase();
	private Bitmap moonImage;
	private RectF oval = new RectF();

	public MoonView(Context context) {
		super(context);
		loadMoonImage(context);
	}

	private void loadMoonImage(Context context) {
		Drawable monDrawable = context.getResources().getDrawable(
				R.drawable.moon);
		int w = monDrawable.getIntrinsicWidth();
		int h = monDrawable.getIntrinsicHeight();
		moonImage = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(moonImage);
		monDrawable.setBounds(0, 0, w, h);
		monDrawable.draw(canvas);
	}

	public MoonView(Context context, AttributeSet attrs) {
		super(context, attrs);
		loadMoonImage(context);
	}

	public MoonView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		loadMoonImage(context);
	}

	@Override
	protected void onDraw(Canvas g) {
		// Create new each time so it is update on every redraw.
		StarDate date = new StarDate();

		int width = getWidth();
		int height = getHeight();
		double phaseAngle = moon.getPhaseAngle(date);

		int xcenter = width / 2;
		int ycenter = height / 2;

		int moonradius;

		try {
			int w = moonImage.getWidth();
			int h = moonImage.getHeight();
			moonradius = (int) Math.min(w, h) / 2;
			int xslop = (width - w) / 2;
			if (xslop < 0)
				xslop = 0;
			int yslop = (height - h) / 2;
			if (yslop < 0)
				yslop = 0;
			g.drawBitmap(moonImage, xslop, yslop, paint);
		} catch (NullPointerException e) {
			moonradius = (int) (Math.min(width, height) * .4);
			// draw the whole moon disk, in moonColor:
			paint.setColor(moonColor);
			oval.set(xcenter - moonradius, ycenter - moonradius, xcenter
					+ moonradius, ycenter + moonradius);
			g.drawOval(oval, paint);
		}

		/* The phase angle is the angle sun-moon-earth,
		 so 0 = full phase, 180 = new.
		 What we're actually interested in for drawing purposes
		 is the position angle of the sunrise terminator,
		 which runs the opposite direction from the phase angle,
		 so we have to convert. */
		double positionAngle = Math.PI - phaseAngle;
		if (positionAngle < 0.)
			positionAngle += 2. * Math.PI;

		// Okay, now fill in the dark part.
		paint.setColor(earthshineColor);

		double cosTerm = Math.cos(positionAngle);
		//if (cosTerm < 0) cosTerm = -cosTerm;
		double rsquared = moonradius * moonradius;
		int whichQuarter = ((int) (positionAngle * 2. / Math.PI) + 4) % 4;
		int j;
		for (j = 0; j <= moonradius; ++j) {
			double rrf = Math.sqrt(rsquared - j * j);
			int rr = (int) (rrf + .5);
			int xx = (int) (rrf * cosTerm);
			int x1 = xcenter - (whichQuarter < 2 ? rr : xx);
			int w = rr + xx + 1;
			g.drawRect(x1, ycenter - j, w + x1, ycenter - j + 1, paint);
			g.drawRect(x1, ycenter + j, w + x1, ycenter + j + 1, paint);
		}
	}
}