/***********************************************************
 * Create framework
 ***********************************************************/
(function ($, doc, win, Snap) {
    "use strict";

    function Donut(el, opts) {
        this.$el = $(el);
        this.opts = opts;
        this.snap = Snap(el);

        this.startShowAnimation = Donut.prototype.startShowAnimation;
  
        this.init();
    }

    /***********************************************************
     * Init donut
     ***********************************************************/
    Donut.prototype.init = function () {
        this.drawLegend();
        this.drawBaseCircle();
    };

    /***********************************************************
     * Draw base circle
     ***********************************************************/
    Donut.prototype.drawBaseCircle = function () {
        var s = this.snap,
            o = this.opts;

        // create diagonal pattern
        var pattern = s.path("M10-5-10,15M15,0,0,15M0-5-20,15").attr({
            fill: "none",
            stroke: "none",
            strokeWidth: 0
        });

        // create masking circle
        var mask = s.circle(o.center.y, o.center.y, o.radius).attr({
            fill: pattern
        });

        // create circle
        Donut.prototype.circle = s.circle(o.center.y, o.center.y, o.radius).attr({
            fill: "r(0.5, 0.5, 0.5)#FFC575-#fff",
            mask: mask,
            stroke: '#D9D9D9',
            strokeWidth: 0,
            opacity: 0
        });

        // create border circle
        s.circle(o.center.y, o.center.y, o.radius).attr({
            stroke: '#D9D9D9',
            fill: 'none',
            strokeWidth: 0
        });
    };

    /***********************************************************
     * Draw legend
     ***********************************************************/
    Donut.prototype.drawLegend = function () {
        var s = this.snap,
            o = this.opts,
            data = o.data;

        var x = o.center.x + o.radius + 50,
            step = 30,
            radius = 6,
            y = o.center.y - (data.length / 2 * step) + radius / 2 + (step - radius) / 2;

        for (var i = 0; i < data.length; i++) {
            var d = data[i];

            d.legend = {
                baseCircle: s.circle(x, y, radius),
                baseCircleRadius: radius,
                text: s.text(x + step, y + radius / 2, d.label),
                center: {
                    x: x,
                    y: y,
                }
            }

            d.legend.baseCircle.attr({
                stroke: '0',
                fill: 'none',
                strokeWidth: 0,
              color:''
            });

            y += step;
        }
    };

    /***********************************************************
     * Build an arc svg path
     ***********************************************************/
    Donut.prototype.buildArcPath = function (center, radius, degreesStart, degreesEnd) {
        var start = this.translatedPoint(center, radius, degreesStart),
            end = this.translatedPoint(center, radius, degreesEnd),
            largeArc = (degreesEnd - degreesStart) > 180 ? 1 : 0;

        return "M" + start.x + "," + start.y + " A" + radius + "," + radius + " 0 " + largeArc + ",1 " + end.x + "," + end.y;
    };
      
    /***********************************************************
     * Animate an arc throw his degrees 
     ***********************************************************/
    Donut.prototype.animateArcByDegrees = function (arc, duration, callback) {
        var s = this.snap,
            t = this;

        Snap.animate(arc.degreesStart, arc.degreesEnd,
            function (degrees) {
                if (arc.draw) {
                    arc.draw.remove();
                }

                arc.path = t.buildArcPath(arc.center, arc.radius, arc.degreesStart, degrees);
                arc.draw = s.path(arc.path);

                arc.draw.attr({
                    stroke: arc.color,
                    fill: 'none',
                    strokeWidth: arc.strokeWidth,
                    cursor: 'pointer'
                });
            },
            duration,
            mina.linear,
            function () {
                if (callback) {
                    callback();
                }
            });
    };

    /***********************************************************
     * Animate an arc throw his stroke width 
     ***********************************************************/
    Donut.prototype.animateArcByStroke = function (arc, strokeWidthStart, strokeWidthEnd, duration, callback) {
        var s = this.snap,
            t = this;

        Snap.animate(strokeWidthStart, strokeWidthEnd,
            function (strokeWidth) {
                if (arc.draw) {
                    arc.draw.remove();
                }

                var radius = arc.radius + (strokeWidth - arc.strokeWidth) / 6;
                arc.path = t.buildArcPath(arc.center, radius, arc.degreesStart, arc.degreesEnd);
                arc.draw = s.path(arc.path);

                arc.draw.attr({
                    stroke: arc.color,
                    fill: 'none',
                    strokeWidth: strokeWidth,
                    cursor: 'pointer'
                });
            },
            duration,
            mina.bounce,
            function () {
                if (callback) {
                    callback();
                }
            });
    };

    /***********************************************************
     * Create the legend circle
     ***********************************************************/
    Donut.prototype.createLegendCircle = function (c) {
        c.draw = this.snap.circle(c.x, c.y, c.radius);
        c.draw.attr({
          fill: c.color
        });
    };

    /***********************************************************
     * Start show animation of legend circle
     ***********************************************************/
    Donut.prototype.animateShowLegendCircle = function (c, duration) {
        c.draw.transform('s0,'+c.x+','+c.y)
        c.draw.animate({ transform: 's1,'+c.x+','+c.y }, duration, mina.bounce);
    };

    /***********************************************************
     * Start show animation of donut and legend for one data entry
     ***********************************************************/
    Donut.prototype.startShowAnimationOneEntry = function (d, percentStart, percentEnd, center, radius, callback) {
        d.arc = {
          percentStart : percentStart,
          percentEnd : percentEnd,
          degreesStart : parseFloat(percentStart) / 100 * 360,
          degreesEnd : parseFloat(percentEnd) / 100 * 360,
          color : d.color,
          strokeWidth : 40,
          center: center, 
          radius: radius,
        }
      
        this.animateArcByDegrees(d.arc, 900, callback);
      
        d.legend.circle = {
          color : d.color,
          x : d.legend.center.x,
          y : d.legend.center.y,
          radius: d.legend.baseCircleRadius + 2
        }
        
        this.createLegendCircle(d.legend.circle);
        this.animateShowLegendCircle(d.legend.circle, 400);
    };

    /***********************************************************
     * Translate a point by some degrees via a center and a radius
     ***********************************************************/
    Donut.prototype.translatedPoint = function (center, radius, degrees) {
        var radians = Math.PI * (degrees - 270) / 180;
        return {
            x: center.x + radius * Math.cos(radians),
            y: center.y + radius * Math.sin(radians),
        }
    };

    /***********************************************************
     * Highlight entry element legend circle and arc
     ***********************************************************/
    Donut.prototype.hightlightElement = function (d) {
        var s = this.snap,
            o = this.opts,
            data = o.data;
      
        if(this.previousHighlightElement == d){
          return;
        }
      
        if(this.previousHighlightElement){
          this.normalElement(this.previousHighlightElement);
        }
        this.previousHighlightElement = d;
      
        var c = d.legend.circle;
        c.draw.animate({ transform: 's1.3,'+c.x+','+c.y }, 200, mina.bounce);
      
        this.animateArcByStroke(d.arc, d.arc.strokeWidth, d.arc.strokeWidth + 20, 500);
    };

    /***********************************************************
     * Normal entry element legend circle and arc
     ***********************************************************/
    Donut.prototype.normalElement = function (d) {
        var s = this.snap,
            o = this.opts,
            t = this,
            data = o.data;
      
        var c = d.legend.circle;
        c.draw.animate({ transform: 's1,'+c.x+','+c.y }, 500, mina.bounce);
      
        this.animateArcByStroke(d.arc, d.arc.strokeWidth + 6, d.arc.strokeWidth, 500, function(){
          d.arc.draw.mouseover(function () {
            t.hightlightElement(d);
          });
          d.arc.draw.click(function () {
            t.hightlightElement(d);
          });
        });
    };

    /***********************************************************
     * Init animation interaction
     ***********************************************************/
    Donut.prototype.initInteraction = function (d, step) {
        var s = this.snap,
            t = this,
            l = d.legend,
            a = d.arc;
          
        l.button = s.rect(l.center.x - 2 * l.baseCircleRadius, l.center.y - step / 2, 200, step);

        l.button.attr({
          opacity: 0,
          cursor: 'pointer',
          color:'red'
        });

        l.button.mouseover(function () {
          t.hightlightElement(d);
          
          
        });
        l.button.click(function () {
          t.hightlightElement(d);
          
        });
      
        a.draw.mouseover(function () {
          t.hightlightElement(d);
            
          
        });
        a.draw.click(function () {
          t.hightlightElement(d);
        });
    };

    /***********************************************************
     * Init animation interactions after showing animation
     ***********************************************************/
    Donut.prototype.initInteractions = function () {
        var s = this.snap,
            o = this.opts,
            t = this,
            data = o.data;
      
        for (var i = 0; i < data.length; i++) {
            this.initInteraction(data[i], 30);
        }
    };

    /***********************************************************
     * Start show animation of donut and legend for all data entry
     ***********************************************************/
    Donut.prototype.startShowAnimation = function (index, totalPct, callback) {
        if(index && !totalPct){
          callback = index;
          index = totalPct;
        }
      
        var s = this.snap,
            o = this.opts,
            t = this,
            data = o.data;
      
        var i = 0,
            total = 0;
      
        if(index){
          i = index;
          total = totalPct;
        }else{
          for(var j = 0 ; j < data.length ; j++){
            var d = data[j];
            if(d.arc && d.arc.draw){
              d.arc.draw.remove();
            }
            if(d.legend && d.legend.circle && d.legend.circle.draw){
              d.legend.circle.draw.remove();
            }
          }
          
          Snap.animate(0, 0.5, function (value) {
              Donut.prototype.circle.attr({
                opacity: value
              });
          }, 800);
        }
      
        if(data.length > i){
          var d = data[i];
          this.startShowAnimationOneEntry(d, total, total + d.value, o.center, o.radius, function(){
            t.startShowAnimation(i+1, total + d.value, callback);
          });
        }else{
          this.initInteractions();
          if(callback){
            callback();
          }
        }
    };

    /***********************************************************
     * Requesting framework
     ***********************************************************/
    $.fn.donut = function (opts) {
        var donuts = [];
      
        this.each(function () {
            donuts.push(new Donut(this, opts));
        });
      
        if(donuts.length == 1){
          return donuts[0];
        }
      
        return donuts;
    };
})(jQuery, document, window, Snap);

/***********************************************************
 * Start framework
 ***********************************************************/
var donutSize = 230;
var donut = $('#prfmnc-chrt').donut({
    donutSize: donutSize,
    center: {
        x: donutSize / 2,
        y: donutSize / 2
    },
    radius: donutSize * 0.3 / 1,
    data: programmingSkills
});

donut.startShowAnimation(function(){
  $('button').attr('disabled', false);
});