package ch.epfl.isochrone.tiledmap;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;

import ch.epfl.isochrone.geo.PointOSM;
import ch.epfl.isochrone.timetable.FastestPathTree;
import ch.epfl.isochrone.timetable.Stop;

/**
 * Classe servant un fournisseur de tuile isochrone
 * 
 * @author Charles Thiebaut (238935)
 * @author Arnaud Delamare (234841)
 * 
 */
public final class IsochroneTileProvider implements TileProvider {
    private FastestPathTree tree;
    private ColorTable colorTable;
    private double speed;

    /**
     * 
     * @param tree
     *            L'arbre des trajets
     * @param colorTable
     *            La table des couleurs pour les différentes tranches
     * @param speed
     *            La vitesse de marche à pied
     */
    public IsochroneTileProvider(FastestPathTree tree, ColorTable colorTable,
            double speed) {
        this.tree = tree;
        this.colorTable = colorTable;
        this.speed = speed;
    }

    /**
     * Retourne la Tile aux coordonnées demandées, en créant des disques de
     * différentes couleurs selon le temps d'arrivée aux différents arrêts
     * 
     * 
     * @param zoom
     *            Le zoom de la Tile
     * 
     * @param x
     *            La position x de la Tile
     * 
     * @param y
     *            La position y de la Tile
     */
    @Override
    public Tile tileAt(int zoom, int x, int y) {

        double pixelLengthX = new PointOSM(zoom, x * 256, y * 256).toWGS84()
                .distanceTo(new PointOSM(zoom, x * 256 + 1, y * 256).toWGS84()); // la
                                                                                 // largeur
                                                                                 // d'un
                                                                                 // pixel
                                                                                 // en
                                                                                 // m
        double pixelLengthY = new PointOSM(zoom, x * 256, y * 256).toWGS84()
                .distanceTo(new PointOSM(zoom, x * 256, y * 256 + 1).toWGS84());

        BufferedImage image = new BufferedImage(256, 256,
                BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();

        g.setColor(colorTable.sliceColor(colorTable.numberOfSlice()));
        g.fillRect(0, 0, image.getWidth(), image.getHeight());
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON); // on met de l'anti-aliasing
                                                    // pour que l'image ne soit
                                                    // pas pixelisée

        for (int i = colorTable.numberOfSlice(); i >= 1; i--) {
            for (Stop s : tree.stops()) {
                int t = colorTable.sliceLength() * i - tree.arrivalTime(s)
                        + tree.startingTime();
                if (t > 0) {
                    double r1 = speed * t / pixelLengthX;
                    double r2 = speed * t / pixelLengthY;

                    // pour chaque tranche de couleur et pour chaque arret, on
                    // crée une ellipse avec les rayons proportionnels au temps
                    // de marche restant

                    g.setColor(colorTable.sliceColor(i - 1));
                    g.fill(new Ellipse2D.Double(s.position().toOSM(zoom).x()
                            - new PointOSM(zoom, x * 256, y * 256).roundedX()
                            - r1, s.position().toOSM(zoom).roundedY()
                            - new PointOSM(zoom, x * 256, y * 256).y() - r2,
                            r1 * 2, r2 * 2));
                }
            }
        }

        return new Tile(x, y, zoom, image);
    }

}
