function Chart(parent, serverTime) {
    this.candles = [];
    this.orders = [];
    this.toOrdersClosed = [];
    this.ordersClosed = {};
    this.parent = parent;
    this.pricePy = 0;
    this.priceOffset = 0;
    this.candleWidthTo = 9;
    this.candlesFreeSpaceTo = 3;
    this.candleWidth = 9;
    this.candlesFreeSpace = 3;
    this.candlesOffset = 0;
    this.speed = 0;
    this.blur = 10;
    this.blurPlus = true;
    this.lWheel = serverTime.now();
    this.toClick = [];
    this.click = [];
    this.serverTime = serverTime;
    this.now = serverTime.now();
    this.lastDrag = Date.now();
}
//Chart.prototype.remove = function () {
//    if(this.bgCanvas) {
//        this.parent.removeChild(this.bgCanvas);
//        this.bgCanvas.remove();
//    }
//    if(this.mainCanvas) {
//        this.parent.removeChild(this.mainCanvas);
//        this.mainCanvas.remove();
//    }
//    if(this.frontCanvas) {
//        this.parent.removeChild(this.frontCanvas);
//        this.frontCanvas.remove();
//    }
//};
Chart.prototype.init = function() {
    this.bgCanvas = document.createElement("canvas");
    this.mainCanvas = document.createElement("canvas");
    this.frontCanvas = document.createElement("canvas");
    this.bgCanvas.className = 'ct-chart ct-chart-bg';
    this.mainCanvas.className = 'ct-chart ct-chart-main';
    this.frontCanvas.className = 'ct-chart ct-chart-front';
    this.parent.appendChild(this.bgCanvas);
    this.parent.appendChild(this.mainCanvas);
    this.parent.appendChild(this.frontCanvas);
    this.mainCanvas.style.zIndex = 100;

    this.bgCanvas.width = this.parent.clientWidth;
    this.mainCanvas.width = this.parent.clientWidth;
    this.frontCanvas.width = this.parent.clientWidth;

    this.bgCanvas.height = this.parent.clientHeight;
    this.mainCanvas.height = this.parent.clientHeight;
    this.frontCanvas.height = this.parent.clientHeight;


    this.mainCanvasCtx = this.mainCanvas.getContext("2d");

    this.candlesPerPage = Math.ceil(this.mainCanvas.clientWidth / (this.candlesFreeSpace * 2 + this.candleWidth));
    this.height = this.parent.clientHeight;
    this.width = this.parent.clientWidth;

    this.mousePosPrice = new PriceLine(this.mainCanvasCtx, this);
    this.mousePosTime = new TimeLine(this.mainCanvasCtx, this);
    var $this = this;
    this.offset = 0;


    this.clientWidth = this.mainCanvas.clientWidth;
    this.clientHeight = this.mainCanvas.clientHeight;

    this.config = {
        chart: {
            bg: '#1F232E',
            linear: {
                color: '#02B6F2',
                bg: ['#1D506B', '#1F2834'],
                point: {
                    bg: '#FFFFFF',
                    shadow: '#556E78'
                }
            }
        },
        timeLine: {
            bg: '#1F232E',
            line: {
                color: '#728C96',
                lineDash: [4, 1]
            },
            text: {
                color: '#728B96',
                font: "12px Arial",
                format: 'HH:mm:ss'
            },
        },
        priceLine: {
            line: {
                color: '#728C96',
                lineDash: [4, 1]
            },
            text: {
                color: '#728C96',
                font: '15px Arial'
            }
        },
        currentTime: {
            line: {
                color: '#3B4359',
            },
            text: {
                format: 'HH:mm:ss',
                bg: '#3B4359',
                font: "12px Arial",
                color: '#F7F7F8'
            }
        },
        currentPrice: {
            bg: '#F74A5C',
            line: {
                color: '#F74A5C',
            },
            text: {
                font: "12px Arial",
                color: '#fff'
            }
        },
        mousePos: {
            bg: '#3B4359'
        },
        clock: {
            color: '#7F9CA7',
            font: "20px Arial",
            format: 'mm:ss'
        },
        order: {
            call: {
                color: '#6CA924'
            },
            put: {
                color: '#F74A5C'
            },
            lineDash: [4, 1],
            font: '12px Arial',
            price: {
                font: 'bold 12px Arial'
            },
            time: {
                font: '12px Arial',
                format: 'HH:mm:ss'
            }
        },
        imageDed: {
            text: 'Time expiration',
            textPosX: -10,
            textPosY: 17,
            color: "#A63947",
            font: "15px Arial"
        },
        imageEnd: {
            text: 'Time expiration',
            textPosX: -10,
            textPosY: 17,
            color: "#A63947",
            font: "13px Arial"
        },
        endLine: {
            lineStyle: "#990F14",
            lineDash: [4, 1]
        }
    }


    this.imageDed = new Image();
    this.imageEnd = new Image(); {
        var bufCanvas = document.createElement("canvas");
        bufCanvas.height = 200;

        var buf = bufCanvas.getContext("2d");

        buf.save();
        buf.rotate(3 * Math.PI / 2);
        buf.font = this.config.imageDed.font;
        buf.fillStyle = this.config.imageDed.color;
        buf.textAlign = "right";
        buf.fillText(this.config.imageDed.text, this.config.imageDed.textPosX, this.config.imageDed.textPosY);
        this.imageDed.src = bufCanvas.toDataURL();
        buf.restore();


        buf.save();
        //buf.rotate(-3 * Math.PI / 2);
        buf.clearRect(-1, -1, bufCanvas.height + 2, bufCanvas.width + 2);
        buf.restore();


        buf.save();
        buf.rotate(3 * Math.PI / 2);

        //buf.clearRect(0, 0, bufCanvas.width, bufCanvas.height);
        //buf.clearRect(-200, -200, 300, 300);
        //buf.rotate(3 * Math.PI / 2);

        buf.font = this.config.imageEnd.font;

        buf.fillStyle = this.config.imageEnd.color;
        buf.textAlign = "right";
        buf.fillText(this.config.imageEnd.text, this.config.imageEnd.textPosX, this.config.imageEnd.textPosY);
        this.imageEnd.src = bufCanvas.toDataURL();
        buf.restore();
        bufCanvas.remove();
    }

    this.endLine = new EndLine(this.mainCanvasCtx, this, {
        lineStyle: this.config.endLine.lineStyle,
        lineDash: this.config.endLine.lineDash,
        lineName: this.imageEnd,
        displayTime: false
    });


    this.scrollOn = false;
    this.mainCanvas.onmousedown = function(e) {
        var evt = e || event;
        $this.dragging = true;
        $this.lastX = evt.offsetX;
        $this.offset = 0;
        $this.translateTime = $this.now;
        $this.translateTo = 0;
        if (window.getSelection) {
            if (window.getSelection().empty) { // Chrome
                window.getSelection().empty();
            } else if (window.getSelection().removeAllRanges) { // Firefox
                window.getSelection().removeAllRanges();
            }
        } else if (document.selection) { // IE?
            document.selection.empty();
        }
    };

    this.mainCanvas.onclick = function(e) {
        $this.scrollOn = true;
        for (var i = 0; i < $this.click.length; i++) {
            var ob = $this.click[i];
            if (
                ob.xs <= e.offsetX && e.offsetX <= ob.xe &&
                ob.ys <= e.offsetY && e.offsetY <= ob.ye
            ) {
                ob.fn();
            }
        }
    };

    this.mainCanvas.onmousemove = function(e) {
        var evt = e || event;
        $this.mouseX = evt.offsetX;
        $this.mouseY = evt.offsetY;
        $this.lastDrag = $this.now;
        if ($this.dragging) {
            var delta = evt.offsetX - $this.lastX;
            $this.lastX = evt.offsetX;
            $this.scrollX(delta);
            $this.translateTo += delta;
        }
    };

    this.mainCanvas.onmouseup = function() {
        if ($this.dragging) {
            $this.speed = Math.round(1000 * $this.translateTo / Math.pow($this.now - $this.translateTime, 2));
        }
        $this.dragging = false;
    };
    this.mainCanvas.onmouseleave = function() {
        $this.dragging = false;
        $this.scrollOn = false;
    };


    var onWheel = function(e) {
        e = e || window.event;
        if (!$this.scrollOn) {
            return;
        }
        var delta = e.deltaY || e.detail || e.wheelDelta;
        var mov = 1;
        if ($this.now - $this.lWheel < 1000) {
            mov = Math.round(1000 / ($this.now - $this.lWheel));
            if (mov > 5) {
                mov = 5;
            }
        }
        $this.lWheel = $this.now;
        if (delta > 0) {
            $this.candleWidthTo -= mov;
            if ($this.candleWidthTo <= 0) {
                $this.candleWidthTo = 1;
            }
        } else if (delta < 0) {
            $this.candleWidthTo += mov;
        }
        $this.candlesFreeSpaceTo = Math.round($this.candleWidthTo / 3);
        if ($this.candlesFreeSpaceTo < 1) {
            $this.candlesFreeSpaceTo = 1;
        }
        if ($this.candlesFreeSpaceTo > 3) {
            $this.candlesFreeSpaceTo = 3;
        }
        e.preventDefault ? e.preventDefault() : (e.returnValue = false);
    };

    if (this.mainCanvas.addEventListener) {
        if ('onwheel' in document) {
            // IE9+, FF17+, Ch31+
            this.mainCanvas.addEventListener("wheel", onWheel);
        } else if ('onmousewheel' in document) {
            // ���������� ������� �������
            this.mainCanvas.addEventListener("mousewheel", onWheel);
        } else {
            // Firefox < 17
            this.mainCanvas.addEventListener("MozMousePixelScroll", onWheel);
        }
    } else { // IE8-
        this.mainCanvas.attachEvent("onmousewheel", onWheel);
    }
};
Chart.prototype.scrollX = function(delta) {
    var $this = this;
    $this.offset += delta;
    if (Math.abs($this.offset) >= $this.candleWidth + $this.candlesFreeSpace * 2) {
        var movCandle = Math.floor($this.offset / ($this.candleWidth + $this.candlesFreeSpace * 2));
        if ($this.candlesOffset + movCandle < 2) {
            $this.offset -= delta;
            return;
        }
        if ($this.candlesOffset + movCandle >= $this.candles.length) {
            $this.offset -= delta;
            return;
        }

        $this.candlesOffset += movCandle;
        $this.offset -= movCandle * ($this.candleWidth + $this.candlesFreeSpace * 2);
    }
};
Chart.prototype.getX = function(time) {
    if (!this.candlesShow || this.candlesShow.length == 0) {
        return 0;
    }
    var ss = 0;
    var s = this.candlesShow.length / 2;
    var sl = this.candlesShow.length - 1;
    for (var i = 0; i < this.candlesShow.length; i++) {
        var candle = this.candlesShow[Math.round(s)];
        if (!candle && Math.round(s) === 1) {
            s = 0;
            continue;
        }
        if (candle.timeId + 1000 > time && time >= candle.timeId) {
            return candle.posX;
        } else if (time < candle.timeId) {
            sl = s;
            s = ss + (sl - ss) / 2;
        } else if (time > candle.timeId) {
            ss = s;
            s = ss + (sl - ss) / 2;
        }
    }
    var lc = this.candlesShow[this.candlesShow.length - 1];
    if (lc.timeId < time) {
        return this.lastPosX + (this.candleWidth + this.candlesFreeSpace * 2) / 1000 * (time - this.now);
    }
    return 0;
};
Chart.prototype.getY = function(price) {
    return this.height - (price * this.pricePy - this.priceOffset);
};
Chart.prototype.getPrice = function(y) {
    return (this.height - y + this.priceOffset) / this.pricePy;
};
Chart.prototype.getTime = function(x) {
    if (!this.candlesShow || this.candlesShow.length == 0) {
        return this.now;
    }
    var zone = this.candleWidth / 2 + this.candlesFreeSpace;
    var ss = 0;
    var s = Math.round(this.candlesShow.length / 2);
    var sl = this.candlesShow.length - 1;
    for (var i = 0; i < this.candlesShow.length; i++) {
        var candle = this.candlesShow[Math.round(s)];
        if (!candle && Math.round(s) === 1) {
            s = 0;
            continue;
        }
        if (candle.posX + zone >= x && x >= candle.posX - zone) {
            return candle.timeId;
        } else if (x < candle.posX) {
            sl = s;
            s = ss + Math.round((sl - ss) / 2);
        } else if (x > candle.posX) {
            ss = s;
            s = ss + Math.round((sl - ss) / 2);
        }
    }
    var lc = this.candlesShow[this.candlesShow.length - 1];
    if (lc.posX < x) {
        //var dd = x - (lc.posX + this.candleWidth + this.candlesFreeSpace * 2);
        var dd = x - this.lastPosX;
        return this.now + 1000 * dd / (this.candleWidth + this.candlesFreeSpace * 2);
    }
};

Chart.prototype.animate = function() {
    this.now = this.serverTime.now();

    if (!this.mainCanvasCtx) {
        return;
    }
    if (this.preparedOrder.symbol === "TRADE_OFF") {
        return;
    }

    this.candlesFreeSpace += (this.candlesFreeSpaceTo - this.candlesFreeSpace) / 5;
    this.candleWidth += (this.candleWidthTo - this.candleWidth) / 5;
    this.candlesPerPage = Math.ceil(this.clientWidth / (this.candlesFreeSpace * 2 + this.candleWidth));

    //this.timePx = this.mainCanvas.clientWidth / this.timeWidth;
    var candle = this.candles[0];
    var timeRR = Math.floor(this.now / 1000) * 1000;
    if (candle && candle.timeId < timeRR) {
        var candle2 = new Candle(timeRR, candle.close, candle.close, candle.close, candle.close, true);
        candle2.closeTo = candle2.close;
        candle2.openTo = candle2.open;
        candle2.minTo = candle2.min;
        candle2.maxTo = candle2.max;
        candle2.animation = 120;
        this.addCandles(candle2);
    }
    this.mainCanvasCtx.clearRect(0, 0, this.width, this.height);

    this.drawPrices();
    this.drawTimes();
    this.drawCandles();

    if (this.preparedOrder && this.preparedOrder.timeFrame && (!this.preparedOrder.optionEnd || this.now >= this.preparedOrder.optionEnd)) {
        //if(!this.optionEnd) {
        this.preparedOrder.optionOff = this.now + this.preparedOrder.timeFrame;
        this.preparedOrder.optionOff = Math.round(this.preparedOrder.optionOff / 1000) * 1000;
        this.preparedOrder.optionEnd = Math.round(this.now + this.preparedOrder.timeFrame - this.preparedOrder.timeOff);
        this.preparedOrder.optionEnd = Math.round(this.preparedOrder.optionEnd / 1000) * 1000;
    }

    this.endLine.draw(this.preparedOrder.optionEnd);

    var text = moment(this.preparedOrder.optionEnd - Date.now()).utc().format(this.config.clock.format);
    this.mainCanvasCtx.font = this.config.clock.font;
    var w1 = this.mainCanvasCtx.measureText(text).width;
    this.mainCanvasCtx.fillStyle = this.config.chart.bg;

    this.mainCanvasCtx.fillRect(this.width / 2 - 2 - w1 / 2, 0, w1, 30);

    this.mainCanvasCtx.beginPath();
    this.mainCanvasCtx.fillStyle = this.config.clock.color;
    this.mainCanvasCtx.textAlign = "center";
    this.mainCanvasCtx.fillText(text, this.width / 2 - 2, 30);

    var orderBuf = [];
    var order = this.orders.pop();
    var closedOrd = [];
    while (order) {
        if (this.now < order.endTime) {
            orderBuf.unshift(order);
            var color;
            if (order.call) {
                color = this.config.order.call.color;
            } else {
                color = this.config.order.put.color;
            }
            new EndLine(this.mainCanvasCtx, this, {
                lineStyle: color,
                bgStyle: this.config.timeLine.bg,
                lineDash: this.config.order.lineDash,
            }).draw(order.endTime, order.openPrice.toFixed(5), order.call, order.startTime, order.endTime, order.amount.toFixed(2) + ' ' + order.currency);
        } else {
            closedOrd.push(order);
        }
        order = this.orders.pop();
    }
    if (closedOrd.length > 0) {
        var cp = this.candles[0];
        order = closedOrd.pop();
        var win = 0;
        while (order) {
            if (order.call && order.openPrice < cp.close) {
                win += 9;
            } else if (!order.call && order.openPrice > cp.close) {
                win += 9;
            } else if (order.openPrice === cp.close) {
                win += 0;
            } else {
                win -= 10;
            }
            order = closedOrd.pop();
        }
        var e1 = document.getElementById("chart-holder");

        var e2 = document.getElementById("win_amt");
        e2.innerHTML = win;

        if (win >= 0) {
            e1.className += ' deal-finished';
        } else {
            e1.className += ' deal-finished loose';
        }
    }

    order = this.toOrdersClosed.pop();
    while (order) {
        this.ordersClosed[order.endTime].count++;
        this.ordersClosed[order.endTime].amount += order.profit;
        order = this.toOrdersClosed.pop();
    }
    for (var orderId in this.ordersClosed) {
        if (this.ordersClosed.hasOwnProperty(orderId)) {
            this.ordersClosed[orderId].draw();
        }
    }

    this.orders = orderBuf;

    this.mousePosPrice.draw(candle.close, this.getY(candle.close), this.config.currentPrice.bg);

    if (this.mouseY > 10 && this.mouseY < this.height - 10 && this.mouseX > 10 && this.mouseX < this.width - 10) {
        this.mousePosPrice.draw(this.getPrice(this.mouseY), this.mouseY, this.config.mousePos.bg);
        this.mousePosTime.draw(this.getTime(this.mouseX));
    }
    if (!this.dragging && Math.abs(this.speed) > 2) {
        this.speed -= this.speed / 20;
        this.scrollX(this.speed);
    }

    this.click = this.toClick;
    this.toClick = [];
};
Chart.prototype.drawPrices = function() {
    var ctx = this.mainCanvasCtx;
    ctx.save();
    var step = 75;
    ctx.font = this.config.priceLine.text.font;
    for (var py = step; py < this.height; py += step) {
        ctx.beginPath();
        ctx.moveTo(0, py);
        ctx.lineTo(this.width, py);
        ctx.strokeStyle = this.config.priceLine.line.color;
        ctx.lineWidth = 1;
        ctx.setLineDash(this.config.priceLine.line.lineDash);
        ctx.stroke();
        ctx.beginPath();
        ctx.fillStyle = this.config.priceLine.text.color;
        ctx.textAlign = "right";
        ctx.fillText(this.getPrice(py).toFixed(5), this.width - 10, py - 5);
    }
    ctx.restore();
};
Chart.prototype.drawTimes = function() {
    var ctx = this.mainCanvasCtx;
    var step = 75;
    ctx.save();
    ctx.fillStyle = this.config.timeLine.bg;
    ctx.moveTo(0, this.height);
    ctx.lineTo(0, this.height - 20);
    ctx.lineTo(this.width, this.height - 20);
    ctx.lineTo(this.width, this.height);
    ctx.lineTo(0, this.height);
    ctx.fill();

    for (var px = step; px < this.width; px += step) {
        ctx.beginPath();
        ctx.moveTo(px, 20);
        ctx.lineTo(px, this.height - 20);
        ctx.strokeStyle = this.config.timeLine.line.color;
        ctx.lineWidth = 1;
        ctx.setLineDash(this.config.timeLine.line.lineDash);
        ctx.stroke();
        ctx.beginPath();
        ctx.font = this.config.timeLine.text.font;
        ctx.fillStyle = this.config.timeLine.text.color;
        ctx.textAlign = "center";
        ctx.fillText(moment(this.getTime(px)).utc().format(this.config.timeLine.text.format), px, this.height - 5);
    }
    ctx.restore();
};

Chart.prototype.drawCandles = function() {
    if (!this.mainCanvasCtx) {
        return;
    }
    //var candles = this.candles;
    this.candlesShow = [];
    for (var ci = this.candlesOffset; ci >= this.candlesOffset - this.candlesPerPage && ci >= 0; ci--) {
        var candle2 = this.candles[ci];
        if (candle2) {
            this.candlesShow.push(candle2)
        } else {
            this.candlesShow.push(this.candles[this.candles.length - 1]);
        }
    }
    if (this.candlesShow.length == 0) {
        return;
    }

    var minPrice = this.candlesShow[0].min;
    var maxPrice = this.candlesShow[0].max;
    for (var i = 0; i < this.candlesShow.length; i++) {
        var candle = this.candlesShow[i];
        candle.draw(this.mainCanvasCtx, this, i, this.candlesShow.length);
        if (minPrice > candle.min) {
            minPrice = candle.min;
        }
        if (maxPrice < candle.max) {
            maxPrice = candle.max;
        }
    }
    var lCandle = this.candlesShow[this.candlesShow.length - 1];
    if (this.lastDrag + 2000 < this.now &&
        lCandle.posX > this.width * 0.75) {
        if (this.candlesOffset < this.width / (this.candlesFreeSpace * 2 + this.candleWidth)) {
            this.lastDrag = this.now;
            this.speed -= Math.abs(lCandle.posX - this.width * 0.5) / (this.candleWidth + this.candlesFreeSpace * 2);
        } else if (this.now - this.lastDraw > 1000) {
            this.lastDrag = this.now;
            this.candlesOffset = 5;
        }
    }
    this.lastDraw = this.now;

    var dif = maxPrice - minPrice;
    if (dif == 0) {
        var split = maxPrice.toString().split('.');
        if (split.length == 2) {
            dif = Math.pow(0.1, split[1].length);
        } else {
            dif = 1;
        }
    }
    maxPrice = maxPrice + dif * 0.2;
    minPrice = minPrice - dif * 0.15;
    if (this.minPrice && this.maxPrice) {
        this.minPrice -= (this.minPrice - minPrice) / 5;
        this.maxPrice -= (this.maxPrice - maxPrice) / 5;
    } else {
        this.minPrice = minPrice;
        this.maxPrice = maxPrice;
    }
    dif = this.maxPrice - this.minPrice;


    this.pricePy = this.clientHeight / dif;
    this.priceOffset = this.minPrice * this.pricePy;
};
Chart.prototype.regClick = function(clickMe) {
    this.toClick.push(clickMe);
};
Chart.prototype.onTick = function(tick) {
    var candle = this.candles[0];
    if (candle && candle.timeId == Math.floor(tick.timeId / 1000) * 1000) {
        if (candle.fake) {
            candle.fake = false;
            candle.open = tick.avg;
            candle.openTo = tick.avg;
            candle.minTo = tick.avg;
            candle.maxTo = tick.avg;
            candle.closeTo = tick.avg;
            candle.animation = 1;
        }
        candle.animation = 1;
        candle.closeTo = tick.avg;
        if (candle.max < tick.avg) {
            candle.maxTo = tick.avg;
            candle.max = tick.avg;
        } else if (candle.min > tick.avg) {
            candle.minTo = tick.avg;
            candle.min = tick.avg;
        }
    }
};
Chart.prototype._addCandle = function(candle) {
    var cn;
    if (candle instanceof Candle) {
        cn = candle;
    } else {
        cn = new Candle(candle.timeId, candle.open, candle.close, candle.min, candle.max);
    }
    if (this.candles.length == 0) {
        this.candles.push(cn);
    } else if (this.candles[0].timeId < cn.timeId) {
        this.candles.unshift(cn);
        this.candlesOffset++;
    } else if (this.candles[this.candles.length - 1].timeId > cn.timeId) {
        this.candles.push(cn);
    } else {
        for (var i = 0; i < 30; i++) {
            if (this.candles[i] && this.candles[i].timeId == cn.timeId) {
                var old = this.candles[i];

                cn.animation = 200;
                cn.minTo = cn.min;
                cn.maxTo = cn.max;
                cn.openTo = cn.open;
                cn.closeTo = cn.close;
                cn.close = old.close;
                this.candles[i] = cn;
                break;
            }
        }
    }
};
Chart.prototype.addCandles = function(candles) {
    var $this = this;
    if (candles instanceof Array) {
        candles.forEach(function(candle) {
            $this._addCandle(candle);
        });
    } else {
        $this._addCandle(candles);
    }
};


function TimeLine(ctx, chart) {
    this.ctx = ctx;
    this.chart = chart;
}
TimeLine.prototype.draw = function(time) {
    this.ctx.beginPath();
    this.ctx.strokeStyle = this.chart.config.currentTime.line.color;
    this.ctx.lineWidth = 1;

    this.ctx.moveTo(this.chart.mouseX, 0);
    this.ctx.lineTo(this.chart.mouseX, this.chart.height);
    this.ctx.stroke();

    this.ctx.beginPath();
    var pagging = 10;
    var height = 20;

    var text = moment(time).utc().format(this.chart.config.currentTime.text.format);
    var w1 = this.ctx.measureText(text).width;
    this.ctx.beginPath();
    this.ctx.fillStyle = this.chart.config.currentTime.text.bg;
    this.ctx.fillRect(this.chart.mouseX - w1 / 2 - pagging, this.chart.height - height, w1 + pagging + pagging, height);

    this.ctx.fillStyle = this.chart.config.currentTime.text.color;


    this.ctx.font = this.chart.config.currentTime.text.font;
    this.ctx.textAlign = "center";
    this.ctx.fillText(text, this.chart.mouseX, this.chart.height - 5);
};

function PriceLine(ctx, chart) {
    this.ctx = ctx;
    this.chart = chart;
}

PriceLine.prototype.draw = function(price, avgPx, bgColor) {
    //var avgPx = this.chart.getY(price);
    //var avgPx = this.chart.mouseY;
    this.ctx.beginPath();
    this.ctx.strokeStyle = bgColor;
    this.ctx.lineWidth = 1;
    this.ctx.moveTo(0, avgPx);
    this.ctx.lineTo(this.chart.width - 10, avgPx);
    this.ctx.stroke();

    this.ctx.moveTo(this.chart.width - 90, avgPx);
    //        this.ctx.lineTo(this.chart.width - 85, avgPx + 5);
    this.ctx.lineTo(this.chart.width - 85, avgPx + 12);
    this.ctx.lineTo(this.chart.width - 10, avgPx + 12);
    this.ctx.lineTo(this.chart.width - 10, avgPx - 12);
    this.ctx.lineTo(this.chart.width - 85, avgPx - 12);
    //        this.ctx.lineTo(this.chart.width - 85, avgPx - 5);
    this.ctx.fillStyle = bgColor;
    this.ctx.fill();

    this.ctx.font = this.chart.config.currentPrice.text.font;
    this.ctx.fillStyle = this.chart.config.currentPrice.text.color;
    this.ctx.textAlign = "left";
    this.ctx.fillText(price.toFixed(5), this.chart.width - 80, avgPx + 4);
};

function EndLine(ctx, chart, config) {
    this.ctx = ctx;
    this.chart = chart;
    if (config) {
        if (config.bgStyle) {

        }
        if (config.bgStyle) {
            this.bgStyle = config.bgStyle;
        }
        if (config.lineDash) {
            this.lineDash = config.lineDash
        }
        if (config.lineStyle) {
            this.lineStyle = config.lineStyle;
        }
        if (config.lineName) {
            this.lineName = config.lineName;
        }
        if (config.displayTime) {
            this.displayTime = config.displayTime;
        }
    }
}
EndLine.prototype.draw = function(time, price, call, startTime, endTime, amount) {
    this.ctx.save();
    this.ctx.beginPath();
    var timeToClose = time;
    var tVal2 = this.chart.getX(time);
    this.ctx.moveTo(tVal2, 0);
    this.ctx.lineTo(tVal2, this.chart.height - 20);
    this.ctx.strokeStyle = this.lineStyle;
    this.ctx.lineWidth = 1;
    if (this.lineDash) {
        this.ctx.setLineDash(this.lineDash);
    }

    this.ctx.stroke();
    if (this.lineName) {
        this.ctx.drawImage(this.lineName, tVal2 - 25, this.chart.height - 145);
    }

    this.ctx.beginPath();
    var number = timeToClose - this.chart.now;
    if (number < 0) {
        number = 0;
    }

    this.ctx.restore();
    if (price) {
        this.ctx.beginPath();
        this.ctx.font = this.chart.config.order.time.font;
        var closeText = moment(time).utc().format(this.chart.config.order.time.format);
        var w2 = this.ctx.measureText(closeText);
        this.ctx.fillStyle = this.bgStyle;
        this.ctx.fillRect(tVal2 - w2.width / 2, this.chart.height - 20, w2.width, 20);

        this.ctx.beginPath();
        this.ctx.fillStyle = this.lineStyle;
        this.ctx.textAlign = "center";

        this.ctx.fillText(closeText, tVal2, this.chart.height - 5);


        var startTX = this.chart.getX(startTime);
        var endTX = this.chart.getX(endTime);
        var priceY = this.chart.getY(price);

        //ctx.arc(startTX, priceY, 4, 0, 2 * Math.PI, false);
        this.ctx.arc(endTX, priceY, 4, 0, 2 * Math.PI, false);
        this.ctx.fillStyle = this.lineStyle;
        this.ctx.fill();
        this.ctx.beginPath();
        this.ctx.moveTo(startTX, priceY);
        if (call) {
            this.ctx.lineTo(startTX + 15, priceY - 15);
            this.ctx.lineTo(startTX + 30, priceY);
            this.ctx.lineTo(startTX, priceY);
            this.ctx.fillColor = this.lineStyle;
            this.ctx.fill();
            this.ctx.beginPath();
            this.ctx.font = this.chart.config.order.price.font;
            this.ctx.fillStyle = this.lineStyle;
            this.ctx.textAlign = "left";
            this.ctx.fillText(price, startTX + 30, priceY - 5);
            this.ctx.fillText(amount, startTX + 30, priceY + 15);
        } else {
            this.ctx.lineTo(startTX + 15, priceY + 15);
            this.ctx.lineTo(startTX + 30, priceY);
            this.ctx.lineTo(startTX, priceY);
            this.ctx.fillColor = this.lineStyle;
            this.ctx.fill();
            this.ctx.beginPath();
            this.ctx.font = this.chart.config.order.price.font;
            this.ctx.fillStyle = this.lineStyle;
            this.ctx.textAlign = "left";
            this.ctx.fillText(price, startTX + 30, priceY + 15);
            this.ctx.fillText(amount, startTX + 30, priceY - 5);
        }
        this.ctx.beginPath();
        this.ctx.strokeStyle = this.lineStyle;
        this.ctx.lineWidth = 2;
        this.ctx.moveTo(startTX, priceY);
        this.ctx.lineTo(endTX, priceY);
        this.ctx.stroke();
    }
};

function Candle(timeId, open, close, min, max, fake) {
    this.timeId = timeId;
    this.open = open;
    this.close = close;
    this.min = min;
    this.max = max;
    this.pos = 0;
    this.animation = 0;
    this.fake = fake;
}
Candle.prototype.draw = function(ctx, chart, nr, total) {
    var offset = nr * (chart.candleWidth + 2 * chart.candlesFreeSpace) + chart.offset;
    if (this.animation == 0) {
        this.closeTo = this.close;
        this.minTo = this.min;
        this.maxTo = this.max;
        this.close = this.open;
        this.min = this.open;
        this.max = this.open;
        this.first = false;
    }
    if (this.animation == 120) {
        this.close = this.closeTo;
        this.min = this.minTo;
        this.max = this.maxTo;
    } else if (this.animation < 120) {
        this.close += (this.closeTo - this.close) / 5;
        this.min += (this.minTo - this.min) / 5;
        this.max += (this.maxTo - this.max) / 5;
    }
    this.animation++;
    this.posX = offset - chart.candleWidth - chart.candlesFreeSpace * 2;
    var d = chart.now;
    var mili = d - this.timeId;
    if (nr == total - 1) {
        var wTotal = (chart.candleWidth + chart.candlesFreeSpace * 2) * 0.001 * mili;
        chart.lastPosX = offset + wTotal - chart.candleWidth - chart.candlesFreeSpace * 2;;
    }
    this.drawLine(ctx, chart, offset, nr, total);
};
Candle.prototype.drawLine = function(ctx, chart, offset, nr, total) {
    if (nr == 0) {
        ctx.beginPath();
        ctx.strokeStyle = chart.config.chart.linear.color;
        ctx.lineWidth = 4;
        ctx.moveTo(this.posX, chart.getY(this.open));
    }
    if (nr <= total - 1) {
        ctx.lineTo(this.posX, chart.getY(this.open));
    }
    if (nr == total - 1) {
        ctx.lineTo(chart.lastPosX, chart.getY(this.close));
        ctx.stroke();

        var grd = ctx.createLinearGradient(0, 0, 0, chart.height - 20);

        for (var i = 0; i < chart.config.chart.linear.bg.length; i++) {
            grd.addColorStop(i, chart.config.chart.linear.bg[i]);
        }
        ctx.fillStyle = grd;
        ctx.lineTo(chart.lastPosX, chart.height - 20);
        ctx.lineTo(0, chart.height - 20);
        ctx.save();
        ctx.fill();
        ctx.restore();

        ctx.save();
        ctx.beginPath();
        ctx.shadowColor = chart.config.chart.linear.point.shadow;
        ctx.fillStyle = chart.config.chart.linear.point.bg;
        if (chart.blurPlus) {
            chart.blur += 40 / 60;
            if (chart.blur > 20) {
                chart.blurPlus = false;
            }
        } else {
            chart.blur -= 40 / 60;
            if (chart.blur < 1) {
                chart.blurPlus = true;
            }
        }
        ctx.arc(chart.lastPosX, chart.getY(this.close), chart.blur / 8 + 1, 0, 2 * Math.PI, false);
        ctx.shadowBlur = chart.blur;
        ctx.fill();

        ctx.restore();
    }
};

function Tick(time, price) {
    return {
        price: price,
        time: time
    }
}

/**
 * requestAnim shim layer by Paul Irish
 * Finds the first API that works to optimize the animation loop,
 * otherwise defaults to setTimeout().
 */
window.requestAnimFrame = (function() {
    return window.requestAnimationFrame ||
        window.webkitRequestAnimationFrame ||
        window.mozRequestAnimationFrame ||
        window.oRequestAnimationFrame ||
        window.msRequestAnimationFrame ||
        function(callback) {
            window.setTimeout(callback, 1000 / 60);
        };
})();

ch = {
    link: function(element) {
        var chart;
        var animateStop = false;
        var serverTime = {
            now: Date.now
        };
        var preparedOrder = {
            symbol: 'EUR/USD',
            optionOff: Math.round(Date.now() / 1000) * 1000 + 10000,
            optionEnd: Math.round(Date.now() / 1000) * 1000 + 10000,
            timeFrame: 10000,
            timeOff: 0
        };

        chart = new Chart(element, serverTime);
        chart.preparedOrder = preparedOrder;
        var symbol = preparedOrder.symbol;
        chart.candlesOffset = 10;
        chart.init();

        var pp = 109.77;
        var candlesAdd = [{
            timeId: Math.round(Date.now() / 1000) * 1000,
            close: pp,
            open: pp,
            min: pp,
            max: pp
        }];
        for (i = 0; i <= 20; i++) {
            var cp = candlesAdd[i];
            pp = cp.close + Math.round((Math.random() - 0.5) * 4) / 1000;
            candlesAdd.push({
                timeId: cp.timeId - 500,
                close: pp,
                open: pp,
                min: pp,
                max: pp
            });
        }
        chart.addCandles(candlesAdd);


        setInterval(function(stomp) {
            var cp = chart.candles[0];
            var mP = 0;
            var mP_CALL = 0;
            var mP_PUT = 0;
            var mc = 0;
            var mC_CALL = 0;
            var mC_PUT = 0;
            var markaPizdec = 0;
            for (i = 0; i < chart.orders.length; i++) {
                var o = chart.orders[i];
                if (o.call && o.endTime > Date.now()) {
                    mc++;
                    mP_CALL += o.openPrice;
                    mC_CALL++;
                } else if (!o.call && o.endTime > Date.now() && cp.close > o.openPrice) {
                    mc--
                    mP_PUT += o.openPrice;
                    mC_PUT++;
                }
            }
            if (mc > 0) {
                mP = mP_CALL / mC_CALL;
                if (mP > cp.close) {
                    markaPizdec = 1;
                }
            } else if (mc < 0) {
                mP = mP_PUT / mC_PUT;
                if (mP < cp.close) {
                    markaPizdec = -1;
                }
            }
            var pp = cp.close + Math.round((Math.random() - 0.5 + markaPizdec * 0.1) * 4) / 1000;
            chart.onTick({
                timeId: Date.now(),
                close: pp,
                open: pp,
                min: pp,
                max: pp,
                avg: pp
            });


        }, 500);

        document.getElementById("btn_call").onclick = function() {
            chart.orders.push({
                id: 1,
                status: "STARTED",
                amount: 10,
                startTime: Date.now(),
                endTime: preparedOrder.optionEnd,
                openPrice: chart.candles[0].close,
                symbol: preparedOrder.symbol,
                currency: 'USD',
                call: true
            });
        };
        document.getElementById("btn_put").onclick = function() {
            chart.orders.push({
                id: 1,
                status: "STARTED",
                amount: 10,
                startTime: Date.now(),
                endTime: preparedOrder.optionEnd,
                openPrice: chart.candles[0].close,
                symbol: preparedOrder.symbol,
                currency: 'USD',
                call: false
            })
        };
        document.getElementById("Apple").onclick = function() {


            var pp = 109.77;
            var candlesAdd = [{
                timeId: Math.round(Date.now() / 1000) * 1000,
                close: pp,
                open: pp,
                min: pp,
                max: pp
            }];
            for (i = 0; i <= 20; i++) {
                var cp = candlesAdd[i];
                pp = cp.close + Math.round((Math.random() - 0.5) * 4) / 1000;
                candlesAdd.push({
                    timeId: cp.timeId - 500,
                    close: pp,
                    open: pp,
                    min: pp,
                    max: pp
                });
            }
            chart.candles = [];
            chart.addCandles(candlesAdd);
            var e1 = document.getElementById("EURUSD");
            var e2 = document.getElementById("GAZPROM");
            var e3 = document.getElementById("Apple");
            e1.className = e1.className.replace('ui-state-active', '');
            e2.className = e2.className.replace('ui-state-active', '');
            e3.className = e3.className += ' ui-state-active';
            chart.candleWidthTo = 9;
            chart.candlesFreeSpaceTo = 3;
            chart.candlesOffset = 10;
        };
        document.getElementById("GAZPROM").onclick = function() {


            var pp = 148.70;
            var candlesAdd = [{
                timeId: Math.round(Date.now() / 1000) * 1000,
                close: pp,
                open: pp,
                min: pp,
                max: pp
            }];
            for (i = 0; i <= 20; i++) {
                var cp = candlesAdd[i];
                pp = cp.close + Math.round((Math.random() - 0.5) * 4) / 1000;
                candlesAdd.push({
                    timeId: cp.timeId - 500,
                    close: pp,
                    open: pp,
                    min: pp,
                    max: pp
                });
            }
            chart.candles = [];
            chart.addCandles(candlesAdd);
            var e1 = document.getElementById("EURUSD");
            var e2 = document.getElementById("Apple");
            var e3 = document.getElementById("GAZPROM");
            e1.className = e1.className.replace('ui-state-active', '');
            e2.className = e2.className.replace('ui-state-active', '');
            e3.className = e3.className += ' ui-state-active';
            chart.candleWidthTo = 9;
            chart.candlesFreeSpaceTo = 3;
            chart.candlesOffset = 10;
        };

        document.getElementById("EURUSD").onclick = function() {


            var pp = 1.14;
            var candlesAdd = [{
                timeId: Math.round(Date.now() / 1000) * 1000,
                close: pp,
                open: pp,
                min: pp,
                max: pp
            }];
            for (i = 0; i <= 20; i++) {
                var cp = candlesAdd[i];
                pp = cp.close + Math.round((Math.random() - 0.5) * 4) / 1000;
                candlesAdd.push({
                    timeId: cp.timeId - 500,
                    close: pp,
                    open: pp,
                    min: pp,
                    max: pp
                });
            }
            chart.candles = [];
            chart.addCandles(candlesAdd);
            var e1 = document.getElementById("Apple");
            var e2 = document.getElementById("GAZPROM");
            var e3 = document.getElementById("EURUSD");
            e1.className = e1.className.replace('ui-state-active', '');
            e2.className = e2.className.replace('ui-state-active', '');
            e3.className = e3.className += ' ui-state-active';
            chart.candleWidthTo = 9;
            chart.candlesFreeSpaceTo = 3;
            chart.candlesOffset = 10;
        };
        document.getElementById("restart-chart").onclick = function() {
            var e1 = document.getElementById("chart-holder");
            e1.className = e1.className.replace('deal-finished', '');
            e1.className = e1.className.replace('loose', '');
            chart.orders = [];
        };

        var animate = function() {
            if (animateStop) {
                return;
            }
            chart.animate();
            requestAnimFrame(animate);
        };
        animate();
    }
};
(function() {
    ch.link(document.getElementById('chart-m'));
})();