class @Calendar
  constructor: (timestamps, @calendar_activities_path) ->
    @currentSelectedDate = ''
    @daySpace = 1
    @daySize = 15
    @daySizeWithSpace = @daySize + (@daySpace * 2)
    @monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
    @months = []

    # 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
        count: count
        date: newDate
        day: day

      i++

    # Init color functions
    @colorKey = @initColorKey()
    @color = @initColor()

    # Init the svg element
    @renderSvg(group)
    @renderDays()
    @renderMonths()
    @renderDayTitles()
    @renderKey()

    @initTooltips()

  renderSvg: (group) ->
    @svg = d3.select '.js-contrib-calendar'
      .append 'svg'
      .attr 'width', (group + 1) * @daySizeWithSpace
      .attr 'height', 167
      .attr 'class', 'contrib-calendar'

  renderDays: ->
    @svg.selectAll 'g'
      .data @timestampsTmp
      .enter()
      .append 'g'
      .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)
            if lastMonth?
              lastMonthX = lastMonth.x

            if !lastMonth?
              @months.push
                month: month
                x: x
            else if month isnt lastMonth.month and x - @daySizeWithSpace isnt lastMonthX
              @months.push
                month: month
                x: x

        "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) =>
        contribText = 'No contributions'

        if stamp.count > 0
          contribText = "#{stamp.count} contribution#{if stamp.count > 1 then 's' else ''}"

        date = dateFormat(stamp.date, 'mmm d, yyyy')

        "#{contribText}<br />#{date}"
      .attr 'class', 'user-contrib-cell js-tooltip'
      .attr 'fill', (stamp) =>
        if stamp.count isnt 0
          @color(Math.min(stamp.count, 40))
        else
          '#ededed'
      .attr 'data-container', 'body'
      .on 'click', @clickDay

  renderDayTitles: ->
    days = [{
      text: 'M'
      y: 29 + (@daySizeWithSpace * 1)
    }, {
      text: 'W'
      y: 29 + (@daySizeWithSpace * 3)
    }, {
      text: 'F'
      y: 29 + (@daySizeWithSpace * 5)
    }]
    @svg.append 'g'
      .selectAll 'text'
      .data days
      .enter()
      .append 'text'
      .attr 'text-anchor', 'middle'
      .attr 'x', 8
      .attr 'y', (day) ->
        day.y
      .text (day) ->
        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: ->
    colorRange = ['#ededed', @colorKey(0), @colorKey(1), @colorKey(2), @colorKey(3)]
    d3.scale
      .threshold()
      .domain([0, 10, 20, 30])
      .range(colorRange)

  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