# Source: objects/chart/Gauge.js

    import {Object2D} from "../../Object2D.js";
    import {ColorStyle} from "../style/ColorStyle";
    import {LinearGradientStyle} from "../style/LinearGradientStyle";

    /**
     * Gauge object is used to draw gauge like graphic.
     *
     * It has a defined range, start angle, end angle and style controls.
     *
     * @class
     * @extends {Object2D}
     */
    function Gauge()
    {
    	Object2D.call(this);

    	/**
    	 * Value displayed by this gauge. It is displayed based on min and max values.
    	 *
    	 * @type {number}
    	 */
    	this.value = 50;

    	/**
    	 * Minimum value of the gauge. Necessary to display the value correctly to scale.
    	 *
    	 * @type {number}
    	 */
    	this.min = 0;

    	/**
    	 * Maximum value of the gauge. Necessary to display the value correctly to scale.
    	 *
    	 * @type {number}
    	 */
    	this.max = 100;

    	/**
    	 * Radius of the gauge object.
    	 *
    	 * @type {number}
    	 */
    	this.radius = 80;

    	/**
    	 * The line width of the gauge semi-circle.
    	 *
    	 * @type {number}
    	 */
    	this.lineWidth = 10;

    	/**
    	 * Start angle of the gauge.
    	 *
    	 * @type {number}
    	 */
    	this.startAngle = Math.PI;

    	/**
    	 * End angle of the gauge.
    	 *
    	 * @type {number}
    	 */
    	this.endAngle = 2 * Math.PI;

    	/**
    	 * If true draw a circular dial at the end of the gauge bar.
    	 *
    	 * @type {boolean}
    	 */
    	this.dial = false;

    	/**
    	 * Style of the base of the gauge object, (the background of the gauge bar).
    	 *
    	 * @type {Style}
    	 */
    	this.baseStyle = new ColorStyle("#e9ecf1");

    	/**
    	 * Style of the gauge bar.
    	 *
    	 * @type {Style}
    	 */
    	this.barStyle = new LinearGradientStyle();
    	this.barStyle.start.set(-100, 0);
    	this.barStyle.end.set(100, 0);
    	this.barStyle.addColorStop(0, "#e5ff50");
    	this.barStyle.addColorStop(0.5, "#50ff67");
    	this.barStyle.addColorStop(1, "#32adff");
    }

    Gauge.prototype = Object.create(Object2D.prototype);
    Gauge.prototype.constructor = Gauge;
    Gauge.prototype.type = "Gauge";
    Object2D.register(Gauge, "Gauge");

    Gauge.prototype.isInside = function(point)
    {
    	return point.length() <= this.radius;
    };

    Gauge.prototype.draw = function(context, viewport, canvas)
    {
    	var percentage = this.value / (this.max - this.min);

    	var range = [this.startAngle, this.endAngle];
    	var diff = range[1] - range[0];
    	var angle = range[0] + diff * percentage;
    	var center = [0, 0];

    	//Back
    	context.lineWidth = this.lineWidth;
    	context.lineCap = "round";
    	context.strokeStyle = this.baseStyle.get(context);
    	context.beginPath();
    	context.arc(center[0], center[1], this.radius, range[0], range[1]);
    	context.stroke();

    	// Fill gradient
    	var gradient = context.createLinearGradient(-this.radius, 0, this.radius, 0);

    	context.strokeStyle = this.barStyle.get(context);

    	context.lineWidth = this.lineWidth;
    	context.beginPath();
    	context.arc(center[0], center[1], this.radius, range[0], angle);
    	context.stroke();

    	if(this.dial)
    	{
    		var dialAngle = (this.startAngle - this.endAngle) * percentage;
    		var dialCenter = [Math.cos(dialAngle) * this.radius, Math.sin(dialAngle) * this.radius];
    		dialCenter[0] = dialCenter[0] - center[0];
    		dialCenter[1] = dialCenter[1] - center[1];

    		context.fillStyle = "#FFFFFF";
    		context.beginPath();
    		context.arc(dialCenter[0], dialCenter[1], this.lineWidth / 2, 0, 2 * Math.PI);
    		context.fill();

    		context.fillStyle = gradient;
    		context.beginPath();
    		context.arc(dialCenter[0], dialCenter[1], this.lineWidth / 3, 0, 2 * Math.PI);
    		context.fill();
    	}
    };

    Gauge.prototype.serialize = function(recursive)
    {
    	var data = Object2D.prototype.serialize.call(this, recursive);

    	data.value = this.value;
    	data.min = this.min;
    	data.max = this.max;
    	data.radius = this.radius;
    	data.lineWidth = this.lineWidth;
    	data.startAngle = this.startAngle;
    	data.endAngle = this.endAngle;
    	data.dial = this.dial;
    	data.baseStyle = this.baseStyle !== null ? this.baseStyle.serialize() : null;
    	data.barStyle = this.barStyle !== null ? this.barStyle.serialize() : null;

    	return data;
    };

    Gauge.prototype.parse = function(data, root)
    {
    	Object2D.prototype.parse.call(this, data, root);

    	this.value = data.value;
    	this.min = data.min;
    	this.max = data.max;
    	this.radius = data.radius;
    	this.lineWidth = data.lineWidth;
    	this.startAngle = data.startAngle;
    	this.endAngle = data.endAngle;
    	this.dial = data.dial;
    	this.baseStyle = data.baseStyle !== null ? Style.parse(data.baseStyle) : null;
    	this.barStyle = data.barStyle !== null ? Style.parse(data.barStyle) : null;
    };

    export {Gauge};