package xaero.rotatenjump.game.object;

import xaero.rotatenjump.game.Game;
import xaero.rotatenjump.game.graphics.Graphics;
import xaero.rotatenjump.game.graphics.model.Model;
import xaero.rotatenjump.game.graphics.model.Right3DPolygon;
import xaero.rotatenjump.misc.Transformations;

/**
 * Created by xaero on 06/07/2017.
 */

public class Platform extends Entity {
    private static final float[] COLOUR = {0.4f, 0.4f, 0.4f, 1f};
    public static float DETACH_STRENGTH = 7.5f;
    private static final Model SIDES4 = new Right3DPolygon(4);
    private static final Model SIDES5 = new Right3DPolygon(5);
    private static final Model SIDES6 = new Right3DPolygon(6);
    private static final Model SIDES7 = new Right3DPolygon(7);
    private static final Model SIDES8 = new Right3DPolygon(8);

    protected static final float DEPTH = 0.5f;//at which the ninja star has to go in
    private int sides;
    protected float lastRotation;
    protected float rotation;
    private float size;
    private float fatness;
    protected float speed;

    protected float rotationRender;//new value
    protected float lastRotationRender;

    public Platform(float posX, float posY, int sides, float rotation, float size, float speed){
        this(posX, posY, sides, rotation, size, size, speed);
    }

    public Platform(float posX, float posY, int sides, float rotation, float size, float fatness, float speed){
        this(posX, posY, sides, rotation, size, size * 2, size * 2, fatness, speed);
    }

    public Platform(float posX, float posY, int sides, float rotation, float size, float renderBoxWidth, float renderBoxHeight, float fatness, float speed){
        super(posX, posY, renderBoxWidth, renderBoxHeight, 2 * fatness);
        this.sides = sides;
        this.rotation = rotationRender = rotation;
        this.lastRotation = lastRotationRender = rotation;
        this.size = size;
        this.fatness = fatness;
        this.speed = speed;
    }

    public float getRotation(float partialCollision) {
        return lastRotation + (rotation - lastRotation) * partialCollision;
    }

    public float getSize() {
        return size;
    }

    @Override
    public void preUpdate() {
        super.preUpdate();
        lastRotation = rotation;
    }

    @Override
    public void update(Game game){
        super.update(game);
        rotation += speed;
    }

    @Override
    public void refresh(){
        super.refresh();
        lastRotationRender = rotationRender;
        rotationRender = rotation;
    }

    private Model getModel(){
        switch(sides){
            case 4: return SIDES4;
            case 5: return SIDES5;
            case 6: return SIDES6;
            case 7: return SIDES7;
            case 8: return SIDES8;
        }
        return null;
    }

    protected float[] getColour(){
        return COLOUR;
    }

    @Override
    public void render(Game game, float partialTicks){
        Graphics.color = getColour();
        getModel().draw(posXRender, posYRender, lastRotationRender + (rotationRender - lastRotationRender) * partialTicks, 0, 0, size, size, fatness);
        /*
        SimpleGraphics.push(canvas);
        paint.setColor(colour);
        SimpleGraphics.scaledTranslate(canvas, posX, posY);
        canvas.rotate(lastRotation + (rotation - lastRotation) * partialTicks);
        SimpleGraphics.drawScaledPolygon(canvas, paint, model);
        SimpleGraphics.pop(canvas);
        */
    }

    @Override
    public boolean isCollidingWith(Player player, float distance, float[][] points, float collisionPartial) {
        if(distance < size + Player.PLAYER_RADIUS){//circles would collide
            float t = 360.0f / sides;
            float b = t / 2;//half of 1 triangle (360 / sides / 2)
            double cosb = Math.cos(Math.toRadians(b));
            //float[][] points = player.getFourPoints(1);//so that it goes a little deeper than 1 pixel
            for(int i = 0; i < 4; i++) { //checkig all 4 points
                float[] point = points[i];//gets one of 4 player points
                float x = (player.posX + point[0]) - getPosX(collisionPartial);
                float y = (player.posY + point[1]) - getPosY(collisionPartial);
                float d = (float) Math.sqrt(x * x + y * y);
                double m = cosb * getSize();//minimal possible collision distance
                if(d < m - DEPTH)
                    return true;
                float a = getAngleFromPlatformNormal(x, y, b, collisionPartial);//angle from the closest triangle "height"
                double cosa = Math.cos(Math.toRadians(a));
                float collisionDistance = (float) (m / cosa) - DEPTH;
                if(d < collisionDistance)
                    return true;
            }
        }
        return super.isCollidingWith(player, distance, points, collisionPartial);
    }

    private float getAngleFromPlatformNormal(float x, float y, float b, float collisionPartial){//angle at which the point is relative to the normal of the side the point is at
        /*
         * x and y are relative to the platform
         * b is 360 / sides / 2
         */
        float o = (float)Math.toDegrees(Transformations.getAngle(x, y)) - getRotation(collisionPartial);
        return -b + (Transformations.wrap(o, (int)(b * 2)));
    }

    public void onAttach(Game game, Player p){
    }

    public void house(Game game, Player p){
        float rotationSinceAttach = rotation - p.getPlatformRotationOnAttach();
        Transformations.rotate(p.getAttachXOffset(), p.getAttachYOffset(), rotationSinceAttach, updateVector2);
        // Log.d("test", attachXOffset + " " + attachYOffset + " " + rotationSinceAttach + " " + Arrays.toString(newOffset));
        p.posX = posX + updateVector2[0];
        p.posY = posY + updateVector2[1];
        p.rotation = p.getRotationOnAttach() + rotationSinceAttach;
    }

    public void onDettach(Player p){
        float offX = p.posX - posX;
        float offY = p.posY - posY;
        float dis = (float) Math.sqrt(offX * offX + offY * offY);
        p.addVelocity(offX / dis * DETACH_STRENGTH, offY / dis * DETACH_STRENGTH);
    }

}
