package com.metaweb.lessen.tokens;

import com.metaweb.lessen.expr.OperatorCall;



public class ComponentColor extends Color {
    protected NumericToken _r, _g, _b, _a;
    
    public ComponentColor(
        int start, int end, String text,
        NumericToken r,
        NumericToken g,
        NumericToken b,
        NumericToken a
    ) {
        super(start, end, text);
        _r = r; _g = g; _b = b; _a = a;
    }
    
    @Override
    public int getA() {
        return tokenToInt(_a);
    }

    @Override
    public int getB() {
        return tokenToInt(_b);
    }

    @Override
    public int getG() {
        return tokenToInt(_g);
    }

    @Override
    public int getR() {
        return tokenToInt(_r);
    }
    
    protected int tokenToInt(NumericToken t) {
        if (t == null) {
            return -1;
        } else if (t.type == Type.Percentage) {
            return t.n.intValue() * 255 / 100;
        } else if (t.n.doubleValue() > 1) {
            return t.n.intValue();
        } else {
            return (int) (255 * t.n.doubleValue());
        }
    }
    
    public Color performOperation(String op, Color color) {
        if (color instanceof ComponentColor && (op.endsWith("+") || op.equals("-"))) {
            ComponentColor color2 = (ComponentColor) color;
            
            NumericToken r = limit(performNumericOperation(op, _r, color2._r));
            NumericToken g = limit(performNumericOperation(op, _g, color2._g));
            NumericToken b = limit(performNumericOperation(op, _b, color2._b));
            NumericToken a = limit(performNumericOperation(op, _a, color2._a));
            
            return createColor(r, g, b, a);
        }
        return super.performOperation(op, color);
    }
    
    @Override
    public Color performOperation(String op, Number n) {
        if (op.equals("*") || op.equals("/")) {
            double d = n.doubleValue();
            NumericToken r = limit(performNumericOperation(op, _r, d));
            NumericToken g = limit(performNumericOperation(op, _g, d));
            NumericToken b = limit(performNumericOperation(op, _b, d));
            NumericToken a = limit(performNumericOperation(op, _a, d));
            
            return createColor(r, g, b, a);
        }
        return super.performOperation(op, n);
    }
    
    protected NumericToken performNumericOperation(String op, NumericToken tLeft, NumericToken tRight) {
        if (tLeft == null) {
            return tRight;
        } else if (tRight == null) {
            return tLeft;
        } else {
            return OperatorCall.performNumericOperation(op, tLeft, tRight);
        }
    }
    
    protected NumericToken performNumericOperation(String op, NumericToken leftT, double d) {
        if (leftT != null) {
            return OperatorCall.performNumericOperation(op, leftT, d);
        }
        return null;
    }
    
    protected ComponentColor createColor(NumericToken r, NumericToken g, NumericToken b, NumericToken a) {
        StringBuffer sb = new StringBuffer();
        sb.append(a != null ? "rgba(" : "rgb(");
        
        sb.append(r != null ? r.getCleanText() : "ERROR"); sb.append(", ");
        sb.append(g != null ? g.getCleanText() : "ERROR"); sb.append(", ");
        sb.append(b != null ? b.getCleanText() : "ERROR");
        if (a != null) {
            sb.append(", ");
            sb.append(a.getCleanText());
        }
        sb.append(")");
        
        return new ComponentColor(
            start, 
            end, 
            sb.toString(), 
            r, 
            g, 
            b, 
            a
        );
    }
    
    protected NumericToken limit(NumericToken t) {
        if (t != null) {
            double d = t.n.doubleValue();
            
            if (t.type == Type.Percentage) {
                if (d < 0 || d > 100) {
                    return OperatorCall.makePercentageToken(t, Math.max(0, Math.min(100, d)));
                }
            } else {
                if (d < 0 || d > 255) {
                    return OperatorCall.makeNumberToken(t, Math.max(0, Math.min(255, d)));
                }
            }
        }
        return t;
    }
}
