package com.sproutlife.renderer.colors;

import java.awt.Color;

import com.sproutlife.model.echosystem.Organism;

public class AngleColorModel extends ColorModel {
    private float primaryHue = 0f;
    private float hueRange = 100;

    @Override
    public void setAttribute(String attribute, Object value) {
        if (attribute.equals("primaryHue")) {
            primaryHue = ((int) value)/360f;
        }
        if (attribute.equals("hueRange")) {
            hueRange = (int) value;
        }
    }

    @Override
    public Color getBackgroundColor() {
        switch (backgroundTheme) {
            case black:
                return Color.black;
            default:
                return Color.white;
        }
    }

    @Override
    public Color getCellColor(Organism o) {
        if (getBackgroundTheme() == BackgroundTheme.white) {
            return getColor(o, primaryHue, 0.7f, 1f);
        }
        else {
            return getColor(o, primaryHue, 0.6f, 1f);
        }
    }

    @Override
    public Color getHeadColor(Organism o) {
        if (getBackgroundTheme() == BackgroundTheme.white) {
            return getColor(o, primaryHue, 1f, 0.8f);
        }
        else {
            return getColor(o, primaryHue, 0.8f, 1f);
        }
    }

    @Override
    public Color getTailColor(Organism o) {
        return getHeadColor(o);
    }

    @Override
    public Color getGenomeBackgroundColor(Organism o) {
        return getColor(o, primaryHue, 0.2f, 1f);
    }

    private Color getColor(Organism o, float h, float s, float br) {
        Organism[] ancestors = new Organism[4];
        Organism a = o;
        for (int ai=0;ai<ancestors.length;ai++) {
            ancestors[ai]=a;
            a = a.getParent();
            if (a==null) {
                return getRandomColor(o);
            }
        }
        double dp1 = getDotProduct(ancestors[0], ancestors[1], ancestors[2]);
        double dp2 = getDotProduct(ancestors[1], ancestors[2], ancestors[3]);

        float r1 = getRotation(dp1);
        float r2 = getRotation(dp2);

        Color c1 = new Color(Color.HSBtoRGB(h+r1, s, br));
        Color c2 = new Color(Color.HSBtoRGB(h+r2, s, br));

        int r = (c1.getRed()*3+c2.getRed()*2)/5;
        int g = (c1.getGreen()*3+c2.getGreen()*2)/5;
        int b = (c1.getBlue()*3+c2.getBlue()*2)/5;

        return new Color(r,g,b);
    }

    private double getDotProduct(Organism o, Organism p, Organism g) {
        double dx1 = o.x-p.x;
        double dy1 = o.y-p.y;
        double dx2 = p.x-g.x;
        double dy2 = p.y-g.y;
        double dist1 = Math.sqrt(dx1*dx1+dy1*dy1);
        double dist2 = Math.sqrt(dx2*dx2+dy2*dy2);
        if (dist1>0) {
            dx1/=dist1;
            dy1/=dist1;
        }
        if(dist2>0) {
            dx2/=dist2;
            dy2/=dist2;
        }
        double dp = dx1*dx2+dy1*dy2;
        //normalized DP should never be more than 1, but sometimes floating point errors occur.
        if (dp>1 || dp<-1) {
           return 1;
        }
        return dp;
    }

    private float getRotation(double dp) {
        float ro = (float) (Math.acos(dp)/Math.PI);
        if (ro>0.5) {
            ro = ro-1;
        }
        return ro*(hueRange/100f);
    }

    private Color getRandomColor(Organism o) {
        float randomHash = (float) ((o.x+o.y)%100/100.0);
        return new Color(Color.HSBtoRGB(randomHash, 0.5f, 1f));
    }
}