function Archive() {

  var activity = false;
  var that = this;
  
  // Fetch active months
  $.ajax({
    url: '/activity.php',
    success: function(data) {
      that._render(data);
    }
  });

  this._render = function(data) {
    this._renderYears(data);
    this._renderMonths(data);
    this._bind(data);
    
    if (this.selectedYear !== undefined) {
      this.selectedYear.click();
    }
  };

  this._renderYears = function(data) {
    // extract the years and sort descending
    var years = [];
    var i = 0;
    var j = 0;
    
    for (var y in data) {
      if (data.hasOwnProperty(y)) {
        years[i++] = y;
      }
    }
    
    years.sort(function (a, b) { return b - a; });
    
    // generate dom elements & append
    var ol = $("<ol>").addClass("years");
    
    for (i = 0, j = years.length; i < j; i++) {
      var a = $("<a>").attr("href","javascript:void(0)").html(years[i]);
      
      if (i === 0) {
        that.selectedYear = a;
      }
      
      ol.append(
        $("<li>").html(a)
      );
    }
    
    $("div.separator-outer").before(ol);
  };
  
  this._renderMonths = function(data) {
    var year = this.selectedYear.html();
    var ol = $("<ol>").addClass("months");
    var months = data[year];
    var names = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
    
    for (var i = 0, j = 12; i < j; i++) {
      var month = names[i];
      
      if (months[i] !== undefined && months[i] == (i + 1)) {
        month = $("<a>").attr("href", "/" + year + "/" + months[i]).html(month);
      }
      
      ol.append(
        $("<li>").html(month)
      );
    }
    
    $("div.separator-outer").after(ol);
  };
  
  function updateYear(elem) {
    var sibs = elem.siblings();
    sibs.find("a").removeClass("selected");
    elem.find("a").addClass("selected");
  }
  
  function updateMonth(elems, activity, year, i) {
    var elem = $(elems[i]);
    
    if (elem.length > 0) {
      var months = activity[year];
      var month = false;
      
      for (var j = 0, k = months.length; j < k; j++) {
        if (months[j] !== undefined && months[j] == (i + 1)) {
          month = months[j];
          break;
        }
      }
      
      elem.fadeOut(90, function() {
        if (month) {
          elem.html(
            $("<a>")
              .attr("href", "/" + year + "/" + month)
              .html(elem.html())
          );
        } else {
          var a = elem.find("a");
          
          if (a.length > 0) {
            month = a.html();
            a.remove();
            elem.html(month);
          }
        }
      }).fadeIn(90, function() {
        updateMonth(elems, activity, year, ++i);
      });
    }
  }

  this._bind = function(data) {
    activity = data;
  
    $("ol.years li").click(function() {
      var li = $(this);
      var year = li.find("a").html();
      
      var morph = $("#morph");
      var offset = li.offset();
      var offsetBody = $("#footer").offset();
    
      if (morph.length === 0) {     
        morph = $("<span>")
          .attr("id","morph")
          .css("top", Math.round(offset.top - offsetBody.top))
          .css("left", Math.round(offset.left - offsetBody.left));
      
        $("ol.years").append(morph);
      }
     
      morph.animate({ 
        width: li.outerWidth(), 
        height: li.outerHeight(), 
        left: Math.round(offset.left - offsetBody.left)
      }, {
        duration: 160,
        easing: 'easeInOutCirc',
        complete: function() {
          updateYear(li);
    
          setTimeout(
            function() {
              updateMonth($("ol.months li"), activity, year, 0);
            }, 50
          );
        }
      });
    
      return false;
    });
  };

}
