(function ($) {
    $.fn.elessarComponent = function (options) {
        if (this instanceof jQuery) {
            var defaultOptions = {
                min: '1.1.2000',
                max: '31.12.2001',
                values: [],
                dateFormat: 'DD.MM.YYYY',
                maxRanges: 1000,
                "label": function (ev) {
                    var i = 1;
                    for (var childKey in this.perant.ranges) {
                        if (this.perant.ranges[childKey] == this) break;
                        i++;
                    }
                    i = this.perant.ranges.length - i + 1;
                    return '<span class="elessar-range-index"># ' + i + '</span>';
                },
            };

            var compOptions = $.extend({}, defaultOptions, options);

            return this.each(function () {
                var thisParentDiv = this;

                if ($(thisParentDiv)[0].rangeBar != undefined) {
                    $(thisParentDiv).empty();
                }

                var minValueCount = moment(compOptions.min, compOptions.dateFormat).valueOf();
                var maxValueCount = moment(compOptions.max, compOptions.dateFormat).valueOf();
                var minWidthSize = (maxValueCount - minValueCount) / 40;

                var maxRangesOption = (compOptions.maxRanges == 1000) ? Infinity : compOptions.maxRanges;

                var rangeBarNew = new RangeBar({
                    min: compOptions.min,
                    max: compOptions.max,
                    values: compOptions.values,
                    barClass: 'progress',
                    rangeClass: 'bar',
                    readonly: false,
                    minSize: minWidthSize,
                    snap: 0,
                    maxRanges: maxRangesOption,
                    allowSwap: false,
                    valueParse: function (date) {
                        return moment(date, compOptions.dateFormat).valueOf();
                    },
                    valueFormat: function (ts) {
                        return moment(ts).format(compOptions.dateFormat);
                    },
                    label: compOptions.label,
                });
                $(this).prepend(rangeBarNew.$el)[0].rangeBar = rangeBarNew;
                var thisSvgElem = $('<div class="svgGraphSpace graphSpace"></div>');
                $(this).prepend(thisSvgElem);
                var svgDraw = SVG(thisSvgElem[0]).size("100%", 100);
                svgDraw.viewbox(0, 0, 800, 100);
                svgDraw.attr("preserveAspectRatio", "none");
                svgDraw.attr("vector-effect", "non-scaling-stroke");
                // $(this)[0].graphCanvas = thisCanvasContext;
                $.fn.elessarComponent.redrawRanges(thisParentDiv);
                $(this).on('changing', function (ev, ranges, changed) {
                    $.fn.elessarComponent.redrawRanges(thisParentDiv);
                }).on('change', function (ev, ranges, changed) {
                    $.fn.elessarComponent.redrawRanges(thisParentDiv);
                })

                $(this).on('remove', function (ev, index) {

                });

                this.getRanges = function () {
                    let vals = $(thisParentDiv)[0].rangeBar.val();
                    var newData = [];
                    for (let i = 0; i < vals.length; i++) {
                        newData.push([vals[i][0], vals[i][1], $(thisParentDiv)[0].rangeBar.ranges[i].$data]);
                    }
                    return newData;
                };

                this.removeAllRanges = function () {
                    for (let i = this.rangeBar.ranges.length - 1; i >= 0; i--) {
                        /* this.rangeBar.ranges[i].remove(); */
                        this.rangeBar.removeRange(this.rangeBar.ranges[i]);
                    }
                }

                this.showGraph = function () {
                    $(thisParentDiv).removeClass('graph-hidden');
                }

                this.hideGraph = function () {
                    $(thisParentDiv).addClass('graph-hidden');
                }

                this.changeRangeAtIndex = function (index, ranges, customData) {
                    index = this.rangeBar.ranges.length - index - 1;
                    ranges[0] = moment(ranges[0], compOptions.dateFormat).valueOf();
                    ranges[1] = moment(ranges[1], compOptions.dateFormat).valueOf();
                    var rangebarWidth = maxValueCount - minValueCount;
                    // prizbusobeni na rozsah range
                    ranges[0] = (ranges[0] - minValueCount) / rangebarWidth;
                    ranges[1] = (ranges[1] - minValueCount) / rangebarWidth;
                    // kontroly at se vejde
                    for (var singleRangeIndex in this.rangeBar.ranges) {
                        if (singleRangeIndex == index) continue;
                        var singleRange = this.rangeBar.ranges[singleRangeIndex];
                        if (ranges[0] > singleRange.range[0] && ranges[1] < singleRange.range[1]) {
                            return 0; // zcela se prekryva s jinym - ignorovat
                        }
                        if (ranges[1] > singleRange.range[0] && ranges[0] < singleRange.range[0] - minWidthSize) {
                            ranges[1] = singleRange.range[0] - minWidthSize;
                        }
                        if (ranges[0] < singleRange.range[1] && ranges[1] > singleRange.range[1] + minWidthSize) {
                            ranges[0] = singleRange.range[1] + minWidthSize;
                        }
                    }
                    if (ranges[0] < 0) {
                        ranges[0] = 0;
                    }
                    if (ranges[1] > 1) {
                        ranges[1] = 1;
                    }
                    this.rangeBar.removeRange(this.rangeBar.ranges[index]);
                    this.rangeBar.addRange(ranges, customData);
                    this.rangeBar.trigger('change', [this.rangeBar.val(), true]);
                    return 1; // provedlo se v poradku
                }

                this.addRange = function (ranges, customData) {
                    if (this.rangeBar.ranges.length >= compOptions.maxRanges) {
                        alert("No more than " + compOptions.maxRanges + " ranges can be added");
                        return;
                    }
                    ranges[0] = moment(ranges[0], compOptions.dateFormat).valueOf();
                    ranges[1] = moment(ranges[1], compOptions.dateFormat).valueOf();
                    // prizbusobeni na rozsah range
                    var rangebarWidth = maxValueCount - minValueCount;
                    ranges[0] = (ranges[0] - minValueCount) / rangebarWidth;
                    ranges[1] = (ranges[1] - minValueCount) / rangebarWidth;
                    this.rangeBar.addRange(ranges, customData);
                    this.rangeBar.trigger('change', [this.rangeBar.val(), true]);
                    return 1;
                }

                this.drawGraph = function (graphData) {
                    var graphValMin = 0;
                    var graphValMax = 0;
                    var atrValMin = 0;
                    var atrValMax = 0;
                    var dateMin = 10000000000000;
                    var dateMax = 0;
                    var hasAttr = (graphData.length > 0 && graphData[0].length > 1);

                    for (dataKey in graphData) {
                        var dataVal = graphData[dataKey][1];
                        var dataDate = moment(graphData[dataKey][0], compOptions.dateFormat).valueOf();
                        dataDate = Math.ceil(dataDate / (1000 * 60 * 60 * 24));
                        if (dataVal > graphValMax) graphValMax = dataVal;
                        if (dataVal > 0.0 && dataVal < graphValMin) graphValMin = dataVal;
                        if (dataDate < dateMin) dateMin = dataDate;
                        if (dataDate > dateMax) dateMax = dataDate;
                        if (hasAttr) {
                            var atrVal = graphData[dataKey][2];
                            if (atrVal > atrValMax) atrValMax = atrVal;
                            if (atrVal > 0.0 && atrVal < atrValMin) atrValMin = atrVal;
                        }
                    }

                    if (hasAttr) {
                        var atrCoeff = graphValMax / atrValMax;
                    }

                    dateMin = Math.ceil(minValueCount / (1000 * 60 * 60 * 24));
                    dateMax = Math.ceil(maxValueCount / (1000 * 60 * 60 * 24));

                    var graphValDiff = graphValMax - graphValMin;
                    var graphValPadding = graphValDiff / 5;
                    graphValMax = graphValMax + (graphValPadding * 2);
                    var graphDateConst = dateMax - dateMin;
                    var graphValConst = graphValMax - graphValMin;
                    graphValConst = graphValConst;
                    graphDateConst = graphDateConst;

                    var xMin = 10000000;
                    var xMax = 0;
                    var xCoords = [];
                    var dataCoords = [];
                    for (dataKey in graphData) {
                        var dataVal = graphData[dataKey][1];
                        var dataDate = moment(graphData[dataKey][0], compOptions.dateFormat).valueOf();
                        dataDate = Math.ceil(dataDate / (1000 * 60 * 60 * 24));
                        var sourY = (dataVal - graphValMin + graphValPadding) * 100 / graphValConst;
                        sourY = 100 - sourY;
                        var sourX = (dataDate - dateMin) * 800 / graphDateConst;
                        xCoords.push(sourX);
                        dataCoords.push(sourX, sourY);
                    }

                    svgDraw.clear();
                    svgDraw.rect(800, 100).fill({
                        color: '#ffffff',
                    }).addClass('oos-rect');;
                    svgDraw.polyline(dataCoords).fill('none').stroke({
                        width: 1,
                        color: '#555555',
                    }).addClass('oos-data-line');

                    thisSvgElem.append($("<div class=\"oos-title-data\">D1, CLOSE PRICE</div>"));

                    if (hasAttr) {
                        // draw atr
                        var i = 0;
                        var atrCoords = [];
                        for (dataKey in graphData) {
                            var dataVal = graphData[dataKey][2];
                            var sourY = ((dataVal * atrCoeff) - graphValMin + graphValPadding) * 100 / graphValConst;
                            sourY = 100 - sourY;
                            var sourX = xCoords[i];
                            atrCoords.push(sourX, sourY);
                            i++;
                        }

                        svgDraw.polyline(atrCoords).fill('none').stroke({
                            width: 1,
                            color: '#ff5555',
                        }).addClass('oos-atr-line');

                        thisSvgElem.append($("<div class=\"oos-title-atr\">(ATR(14))</div>"));
                    }

                };

            });
        }
    };

    $.fn.elessarComponent.redrawRanges = function (parent) {
        var thisGraphTop = $(this).find('.graphSpace').height();
        var thisGraphHeight = thisGraphTop;
        var totalHeight = thisGraphHeight + $(this).find('.elessar-rangebar').height() + 1;
        thisGraphTop = -thisGraphTop - 1;
        $(parent).find('.elessar-range').each(function () {
            if ($(this).find('.graphRange').length <= 0) {
                $(this).find('.elessar-barlabel').before($('<span class="graphRange"></span>'));
            }
            $(this).find('.graphRange').css('top', thisGraphTop + 'px').css('height', thisGraphHeight + 'px');
            $(this).find('.elessar-handle').css('height', totalHeight + 'px');
        });
    }

    $.fn.elessarComponent.removeRangeCustom = function (elem) {
        var thisRangeEl = $(elem).parent().parent();
        var thisElIndex = thisRangeEl.index();
        thisRangeEl.data('element').perant.removeRange(thisElIndex, false, false);
    }

}(jQuery));