package de.hems.trafficsim;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.SurfaceHolder;

import java.util.ConcurrentModificationException;
import java.util.List;

public class Renderer {
    private List<VehicleTimeRecord> stepRecords;
    protected Track track;
    protected int pixelPerVehicle;
    protected int pixelPerLine;
    protected float tooShortPerTrackLength;
    protected float tooShortPerHeight;
    protected Paint paint;
    protected SurfaceHolder holder;
    protected Canvas canvas;
    protected int width;
    protected int height;

    public Renderer(Track track, SurfaceHolder holder) {
        this.track = track;
        this.holder = holder;
        this.paint = new Paint();
    }

    public void setSize(int width, int height) {
        if (width > 0 && height > 0) {
            this.pixelPerVehicle = width / (int) this.track.getTrackLength();
            this.tooShortPerTrackLength =
                    (width - this.pixelPerVehicle * this.track.getTrackLength())
                            / this.track.getTrackLength();
            this.pixelPerLine = height / this.track.getHistoryLength();
            this.tooShortPerHeight = (height - this.pixelPerLine * this.track.getHistoryLength())
                    / (float)height;
            System.out.println("Viewport: "+width+"x"+height);
            this.width = width;
            this.height = height;
        }
    }

    public void setTrack(Track track) {
        this.track = track;
        this.setSize(width, height);
    }

    protected int getColor(float curVelocity, float maxVelocity) {
        float perc = curVelocity / maxVelocity;
        perc = 1 - perc;
        if (perc <= 0.5) {
            int red = ((int) (2*perc*0xFF)) << 16;
            int green = 0xFF << 8;
            int blue = 0;
            return 0xff000000 | red | green | blue;
        } else {
            int red = 0xFF << 16;
            int green = ((int)(0xFF-0xFF*(perc-0.5)*2)) << 8;
            int blue = 0;
            return 0xff000000 | red | green | blue;
        }
    }

    protected void draw() {
        try {
            if (this.pixelPerVehicle == 0) {
                Rect rect = this.holder.getSurfaceFrame();
                this.setSize(rect.right, rect.bottom);
            }
            canvas = this.holder.lockCanvas();
            synchronized (holder) {
                int y = 0;
                int left = 0;
                int hCompensateStart = 0;
                int hCompensateEnd = 0;
                int vCompensateStart = 0;
                int vCompensateEnd = 0;
                canvas.drawColor(Color.BLACK);
                for (int curStepIdx = this.track.getVtrList().size()-1;curStepIdx >= 0;
                     curStepIdx--) {
                    try {
                        try {
                            track.getListSemaphore().acquire();
                        } catch (InterruptedException ex) {
                            return;
                        }
                        vCompensateStart = Math.round(y * this.tooShortPerHeight);
                        vCompensateEnd = Math.round((y+this.pixelPerLine) * this.tooShortPerHeight);
                        stepRecords = this.track.getVtrList().get(curStepIdx);
                        int i = 0;
                        for (VehicleTimeRecord r : stepRecords) {
                            left = (int) (this.pixelPerVehicle * r.getPosition());
                            hCompensateStart = Math.round(r.getPosition() * this.tooShortPerTrackLength);
                            hCompensateEnd = Math.round((r.getPosition() + this.pixelPerVehicle) * this.tooShortPerTrackLength);
                            this.paint.setColor(getColor(r.getVelocity(), r.getMaxVelocity()));
                            canvas.drawRect(left + hCompensateStart, y+vCompensateStart,
                                    left + this.pixelPerVehicle + hCompensateEnd,
                                    y + pixelPerLine + vCompensateEnd, this.paint);
                            i++;
                        }
                        track.getListSemaphore().release();
                        y += pixelPerLine;
                    } catch (ConcurrentModificationException ex) {
                        System.out.println("Concurrent Exception occured, skipping record");
                        y += pixelPerLine;
                    }
                }
            }
        } finally {
            if (canvas != null) {
                this.holder.unlockCanvasAndPost(canvas);
            }
        }
    }
}
