/**
 *  Copyright (C) 2002-2012   The FreeCol Team
 *
 *  This file is part of FreeCol.
 *
 *  FreeCol is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  FreeCol is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with FreeCol.  If not, see <http://www.gnu.org/licenses/>.
 */


package net.sf.freecol.tools;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;

public class FlagTest extends JFrame {

    private static final int[][] layout = new int[51][2];

    static {
	for (int[] bars : new int[][] {
                { 5, 4 }, { 5, 6 }, { 6, 5 }, { 5, 5 }
	     }) {
	    int sum = bars[0] + bars[1];
	    boolean even = true;
	    while (sum < 51) {
		layout[sum] = bars;
		if (even) {
		    sum += bars[0];
		    even = false;
		} else {
		    sum += bars[1];
		    even = true;
		}
	    }
	}

    }

    public class Flag {

	private static final double width = 100;
	private static final double length = 1.9 * width;
	private static final double unionLength = 0.4 * length;
	private static final double star = 0.0616 * width;
	private double unionWidth;

	private final Color red = new Color(.698f, .132f, .203f);
	private final Color blue = new Color(.234f, .233f, .430f);

	private BufferedImage image;

	public Flag(int stars, int stripes) {

	    image = new BufferedImage((int) length, (int) width,
				      BufferedImage.TYPE_INT_RGB);
	    Graphics2D g = image.createGraphics();
	    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
			       RenderingHints.VALUE_ANTIALIAS_ON);

	    g.setColor(red);
	    Rectangle2D.Double background =
		new Rectangle2D.Double(0, 0, length, width);
	    g.fill(background);
	    g.setColor(Color.WHITE);
	    double stripeWidth = width / stripes;
	    Rectangle2D.Double stripe =
		new Rectangle2D.Double(0, 0, length, stripeWidth);
	    AffineTransform transform = g.getTransform();
	    for (int i = 0; i < stripes / 2; i++) {
		g.translate(0, stripeWidth);
		g.fill(stripe);
		g.translate(0, stripeWidth);
	    }
	    g.setTransform(transform);
	    g.setColor(blue);
	    if (stripes == 1) {
		unionWidth = stripeWidth / 2;
	    } else {
		unionWidth = stripeWidth * Math.ceil(stripes / 2.0);
	    }
	    Rectangle2D.Double union =
		new Rectangle2D.Double(0, 0, unionLength, unionWidth);
	    g.fill(union);

	    GeneralPath unionPath;
	    if (stars == 1) {
		unionPath = getPentagram();
	    } else if (stars == 2) {
		unionPath = new GeneralPath();
		unionPath.append(getPentagram(), false);
		GeneralPath newStar = getPentagram();
		newStar.transform(AffineTransform.getTranslateInstance(unionLength/3, 0));
		unionPath.append(newStar, false);
	    } else if (stars < 14) {
		unionPath = getCircleOfStars(stars);
	    } else {
		unionPath = getGrid(stars);
	    }
	    unionPath.transform(AffineTransform
				.getTranslateInstance(-unionPath.getBounds().getX(),
						      -unionPath.getBounds().getY()));
	    double x = unionLength - unionPath.getBounds().getWidth();
	    double y = unionWidth - unionPath.getBounds().getHeight();
	    unionPath.transform(AffineTransform.getTranslateInstance(x/2, y/2));
	    g.setColor(Color.WHITE);
	    g.fill(unionPath);

	}

	public Image getImage() {
	    return image;
	}

	public GeneralPath getGrid(int states) {
	    int[] bars = new int[2];
	    for (int count = states; count < 51; count++) {
		if (layout[count][0] > 0) {
		    bars = layout[count];
		    break;
		}
	    }
	    int maxCols = Math.max(bars[0], bars[1]);
	    int rows = 2;
	    int sum = bars[0] + bars[1];
	    while (sum < states) {
		sum += bars[rows%2];
		rows++;
	    }
	    double hSpace = unionLength / (2 * maxCols);
	    double vSpace = unionWidth / (2 * rows);
	    double y = 0;
	    GeneralPath star = getPentagram();
	    GeneralPath grid = new GeneralPath();
	    int count = 1;
	    for (int row = 0; row < rows; row++) {
		int cols = bars[row%2];
		double x = (cols == maxCols) ? 0 : hSpace;
		for (int col = 0; col < cols; col++) {
		    if (count > states) {
			break;
		    }
		    GeneralPath newStar = (GeneralPath) star.clone();
		    newStar.transform(AffineTransform.getTranslateInstance(x, y));
		    grid.append(newStar, false);
		    x += 2 * hSpace;
		    count++;
		}
		y += 2 * vSpace;
	    }
	    return grid;
	}

	public GeneralPath getPentagram() {
	    double angle = 2 * Math.PI / 5;
	    double y = -star / 2;
	    GeneralPath pentagram = new GeneralPath(GeneralPath.WIND_NON_ZERO);
	    pentagram.moveTo(0, y);
	    int[] vertex = new int[] { 2, 4, 1, 3 };
	    for (int i : vertex) {
		double phi = i * angle;
		double xx = -y * Math.sin(phi);
		double yy = y * Math.cos(phi);
		pentagram.lineTo(xx, yy);
	    }
	    pentagram.closePath();
	    return pentagram;
	}

	public GeneralPath getCircleOfStars(int n) {
	    double radius = 0.3 * unionWidth;
	    double phi = Math.PI * 2 / n;
	    GeneralPath star = getPentagram();
	    GeneralPath circle = new GeneralPath();
	    for (int i = 0; i < n; i++) {
		GeneralPath newStar = (GeneralPath) star.clone();
		double xx = -radius - radius * Math.sin(i * phi);
		double yy = -radius * Math.cos(i * phi);
		newStar.transform(AffineTransform.getTranslateInstance(xx, yy));
		circle.append(newStar, false);
	    }
	    double x = circle.getBounds().getX();
	    double y = circle.getBounds().getY();
	    circle.transform(AffineTransform.getTranslateInstance(-x, -y));
	    return circle;
	}

    }

    public FlagTest() {

	super("FlagTest");
	JPanel panel = new JPanel(new GridLayout(0, 5, 5, 5));
        JScrollPane scrollPane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
                                                 JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	for (int states = 1; states < 51; states++) {
	    Flag flag = new FlagTest.Flag(states, Math.min(13, states));
	    JLabel label = new JLabel(new ImageIcon(flag.getImage()));
	    panel.add(label);
	}
	add(scrollPane);
    }


    public static void main(String[] args) {

	FlagTest frame = new FlagTest();

	// display the window
	frame.pack();
	frame.setVisible(true);


    }

}