 
       i++
 
-    # Color function for chart
-    color = d3
-      .scale
-      .linear()
-      .range(['#acd5f2', '#254e77'])
-      .domain([0, highestValue])
+    # Init color functions
+    @color = @initColor()
+    @colorKey = @initColorKey()
 
-    # Color function for key
-    colorKey = d3
-      .scale
-      .linear()
-      .range(['#acd5f2', '#254e77'])
-      .domain([0, 3])
-    keyColors = ['#ededed', colorKey(0), colorKey(1), colorKey(2), colorKey(3)]
+    # Init the svg element
+    @renderSvg(group)
+    @renderDays()
+    @renderMonths()
+    @renderDayTitles()
+    @renderKey()
 
-    monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
-    months = []
-    svg = d3.select '.js-contrib-calendar'
+    @initTooltips()
+
+  renderSvg: (group) ->
+    @svg = d3.select '.js-contrib-calendar'
       .append 'svg'
-      .attr 'width', 54 * daySizeWithSpace
+      .attr 'width', (group + 1) * @daySizeWithSpace
       .attr 'height', 167
       .attr 'class', 'contrib-calendar'
 
-    # Setup each day box
-    svg.selectAll 'g'
-      .data timestampsTmp
+  renderDays: ->
+    @svg.selectAll 'g'
+      .data @timestampsTmp
       .enter()
       .append 'g'
-      .attr 'transform', (group, i) ->
-        _.each group, (stamp, a) ->
+      .attr 'transform', (group, i) =>
+        _.each group, (stamp, a) =>
           if a is 0 and stamp.day is 0
             month = stamp.date.getMonth()
-            x = (daySizeWithSpace * i + 1) + daySizeWithSpace
-            lastMonth = _.last(months)
+            x = (@daySizeWithSpace * i + 1) + @daySizeWithSpace
+            lastMonth = _.last(@months)
             if lastMonth?
               lastMonthX = lastMonth.x
 
             if !lastMonth?
-              months.push
+              @months.push
                 month: month
                 x: x
-            else if month isnt lastMonth.month and x - daySizeWithSpace isnt lastMonthX
-              months.push
+            else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
+              @months.push
                 month: month
                 x: x
 
-        "translate(#{(daySizeWithSpace * i + 1) + daySizeWithSpace}, 18)"
+        "translate(#{(@daySizeWithSpace * i + 1) + @daySizeWithSpace}, 18)"
       .selectAll 'rect'
       .data (stamp) ->
         stamp
       .enter()
       .append 'rect'
       .attr 'x', '0'
-      .attr 'y', (stamp, i) ->
-        (daySizeWithSpace * stamp.day)
-      .attr 'width', daySize
-      .attr 'height', daySize
-      .attr 'title', (stamp) ->
+      .attr 'y', (stamp, i) =>
+        (@daySizeWithSpace * stamp.day)
+      .attr 'width', @daySize
+      .attr 'height', @daySize
+      .attr 'title', (stamp) =>
         contribText = 'No contributions'
 
         if stamp.count > 0

class @Calendar
  constructor: (timestamps, calendar_activities_path) ->
    currentSelectedDate = ''
    daySpace = 1
    daySize = 15
    daySizeWithSpace = daySize + (daySpace * 2)

    # Get the highest value from the timestampes
    highestValue = 0
    _.each timestamps, (count) ->
      if count > highestValue
        highestValue = count

    # Loop through the timestamps to create a group of objects
    # The group of objects will be grouped based on the day of the week they are
    timestampsTmp = []
    i = 0
    group = 0
    _.each timestamps, (count, date) ->
      newDate = new Date parseInt(date) * 1000
      day = newDate.getDay()

      # Create a new group array if this is the first day of the week
      # or if is first object
      if (day is 0 and i isnt 0) or i is 0
        timestampsTmp.push []
        group++

      innerArray = timestampsTmp[group-1]

      # Push to the inner array the values that will be used to render map
      innerArray.push

        day.text
      .attr 'class', 'user-contrib-text'

  renderMonths: ->
    @svg.append 'g'
      .selectAll 'text'
      .data @months
      .enter()
      .append 'text'
      .attr 'x', (date) ->
        date.x
      .attr 'y', 10
      .attr 'class', 'user-contrib-text'
      .text (date) =>
        @monthNames[date.month]

  renderKey: ->
    keyColors = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
    @svg.append 'g'
      .attr 'transform', "translate(18, #{@daySizeWithSpace * 8 + 16})"
      .selectAll 'rect'
      .data keyColors
      .enter()
      .append 'rect'
      .attr 'width', @daySize
      .attr 'height', @daySize
      .attr 'x', (color, i) =>
        @daySizeWithSpace * i
      .attr 'y', 0
      .attr 'fill', (color) ->
        color

  initColor: ->
    d3.scale
      .linear()
      .range(['#acd5f2', '#254e77'])
      .domain([0, @highestValue])

  initColorKey: ->
    d3.scale
      .linear()
      .range(['#acd5f2', '#254e77'])
      .domain([0, 3])

  clickDay: (stamp) ->
    if @currentSelectedDate isnt stamp.date
      @currentSelectedDate = stamp.date
      formatted_date = @currentSelectedDate.getFullYear() + "-" + (@currentSelectedDate.getMonth()+1) + "-" + @currentSelectedDate.getDate()

      $.ajax
        url: @calendar_activities_path
        data:
          date: formatted_date
        cache: false
        dataType: 'html'
        beforeSend: ->
          $('.user-calendar-activities').html '<div class="text-center"><i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i></div>'
        success: (data) ->
          $('.user-calendar-activities').html data
    else
      $('.user-calendar-activities').html ''

  initTooltips: ->
    $('.js-contrib-calendar .js-tooltip').tooltip
      html: true
