;(function ( $, window, document, undefined ) {

function CPDQMIssueRenderer() {
    this.options = {
      'pulldownId': '#ast-pulldown',
      'pulldownBufferClass': '.ast-pulldown-buffer'
    };
}
CPDQMIssueRenderer.prototype.preparePage = function(){
  this.cleanPage();
  this.createFauxTab();
  this.createPulldownSkeleton();
};

CPDQMIssueRenderer.prototype.run = function(data){


  var length = data.errors.length;
  // Assume backend is not flawed

  if(length){
    var processedJSON = this.processJSON(data);

    this.updateIssueCounts(processedJSON.totalIssues);
    this.createIssuesListModule(processedJSON.highlightedIssues, 'Issues highlighted on page', true);
    this.createIssuesListModule(processedJSON.generalIssues, 'General issues');
    this.updateFauxIssueTab(processedJSON.totalIssues);
  } else {
    this.addCongratulatoryText();
    this.updateIssueCounts(0);
    this.updateFauxIssueTab(0);
  }


  $(this.options.pulldownId).addClass((length) ? 'ast-issues' : 'ast-no-issues');

  this.addFauxTabClickEvent();
};

CPDQMIssueRenderer.prototype.processJSON = function(data){
  var length = data.errors.length,
    totalIssues = 0,
    generalIssues = {},
    highlightedIssues = {};

  for (var i = 0; i < length; i++) {
    var issue = data.errors[i];
    if (issue.componentId === null) {
      this.addIssueToObj(issue, generalIssues);
    } else {
      this.addIssueToObj(issue, highlightedIssues);
      this.highlightIssueInPage(issue);
    }
    totalIssues += issue.checkpoints.length;
  }

  this.setSourceHighlightingHash();

  return {
    'totalIssues': totalIssues,
    'highlightedIssues': this.toArray(highlightedIssues),
    'generalIssues': this.toArray(generalIssues)
  };
};


CPDQMIssueRenderer.prototype.addIssueToObj = function(issue, issuesList) {
  var length = issue.checkpoints.length;
  for (var i = 0; i < length; i++) {
    var checkpoint = issue.checkpoints[i];
    if (!issuesList[checkpoint.id]) {
      checkpoint.instanceCount = 1;
      issuesList[checkpoint.id] = checkpoint;
    } else {
      issuesList[checkpoint.id].instanceCount++;
    }
  }
};

CPDQMIssueRenderer.prototype.cleanPage = function(){
    $(this.options.pulldownId).remove();
    $(this.options.pulldownBufferClass).remove();
    $('#ast-faux-tab').remove();
    // remove component errors
    $('.validation-output').remove();
    // remove styling from erroneous components
    $('.activestandards-validation').removeClass('activestandards-validation activestandards-error');
};

CPDQMIssueRenderer.prototype.createFauxTab = function(){
  var $fauxTab = $('<div />', {
    'id': 'ast-faux-tab',
    'class': 'ast-faux-tab'
  });
  $('<span />').appendTo($fauxTab);
  $fauxTab.prependTo($('body'));


};

CPDQMIssueRenderer.prototype.addFauxTabClickEvent = function(){
  var self = this,
  $fauxTab = $('#ast-faux-tab');

  $fauxTab.one('click', function(){
    self.initialShowPulldown();
    $fauxTab.remove();
    self.tabClick();
  });

};

CPDQMIssueRenderer.prototype.createPulldownSkeleton = function() {

  var $pulldown = $('<div />', {
    'id': 'ast-pulldown',
    'class': 'ast-pulldown ast-invis'
  });

  $('<h2 />').appendTo($pulldown);

  $('<div />', {
    'class': 'ast-content'
  }).append(this.getAstSymbolLink()).appendTo($pulldown);

  var $tab = $('<div />', {
    'id': 'ast-pulldown-tab',
    'class': 'ast-tab'
  }).on('click', this.tabClick);

  $tab.append($('<span />')).appendTo($pulldown);

  $pulldown.appendTo($('body'));

  // Now for the buffer item - this is used to push content down the page when the pulldown is expanded
  var $buffer = $('<div />', {
    'id' : 'ast-pulldown-buffer',
    'class' : 'ast-pulldown-buffer'
  });
  $buffer.prependTo($('body'));

};

CPDQMIssueRenderer.prototype.tabClick = function(){
  var $pulldown = $('#ast-pulldown'),
      $buffer = $('#ast-pulldown-buffer'),
      animationOptions = {
        'duration': 350,
        'queue': false},
      top = $pulldown.css('top'),
      newTop = (top === '0px') ? -$pulldown.outerHeight() : 0,
      bufferNewHeight = (top === '0px') ? 0 : $pulldown.outerHeight();

    $pulldown.toggleClass('ast-pulled');

    $pulldown.animate({
      'top': newTop
    }, animationOptions);

    $buffer.animate({
      'height' : bufferNewHeight
    }, animationOptions);
};

CPDQMIssueRenderer.prototype.getAstSymbolLink = function() {
  var altText = 'Sign in to your Crownpeak DQM';

  return $('<a />', {
    'target': '_blank',
    'title': altText,
    'href': 'https://dqm.crownpeak.com/',
    'class': 'ast-link'
  });
};


CPDQMIssueRenderer.prototype.initialShowPulldown = function() {
  var $pulldown = $(this.options.pulldownId),
    height = $pulldown.outerHeight();
  $pulldown.css({
    'top': -height
  });
  $('#ast-faux-tab').addClass('ast-invis');
  $pulldown.removeClass('ast-invis');
};

CPDQMIssueRenderer.prototype.animateIssuesCount = function(){
    var animationClasses = 'animated bounceIn',
    animationEndEvents = 'webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend',
    animationDelay = {'-webkit-animation-delay' : '0.2s',
      'animation-delay' : '0.2s'},

    $issueCount = $('#ast-faux-tab span');

    if ($issueCount.text().length > 0) {
      $issueCount.css(animationDelay);
      $issueCount.one(animationEndEvents, function(){
        $(this).removeClass(animationClasses);
      }).addClass(animationClasses);
    }
};

CPDQMIssueRenderer.prototype.toArray = function(issues) {
  var array = $.map(issues, function(value) {
    return [value];
  });
  return array;
};

CPDQMIssueRenderer.prototype.updateFauxIssueTab = function(totalIssues){
  var $fauxTab = $('#ast-faux-tab');

  if(totalIssues === 0){
    $fauxTab.addClass('ast-no-issues');
    $fauxTab.children('span').addClass('ast-no-issues-count');
    $fauxTab.children('span').html('<i class="fa fa-check">&nbsp;</i>');

  } else {
    $fauxTab.addClass('ast-issues');
    if(totalIssues < 10){
      $fauxTab.children('span').addClass('ast-single-issue-count');
    }
      $fauxTab.children('span').text(totalIssues);
  }

  this.animateIssuesCount();
};

CPDQMIssueRenderer.prototype.updateIssueCounts = function(totalIssues) {
  var $issuesSpan = $('#ast-pulldown-tab span');
  if (totalIssues > 0) {

    $issuesSpan.text(totalIssues);
    if (totalIssues < 10) {
      $issuesSpan.addClass('ast-single-issue-count');
    }

  } else {
      $issuesSpan.addClass('ast-no-issues-count');
      $issuesSpan.html('<i class="fa fa-check">&nbsp;</i>');
  }

  var h2IssuesText = 'Crownpeak DQM has found ' + totalIssues + ' issue' + (totalIssues === 1 ? ' ' : 's ') + 'on this page';
  $('#ast-pulldown h2').text(h2IssuesText).prependTo($(this.options.pulldownId));
};

CPDQMIssueRenderer.prototype.addCongratulatoryText = function(){
  var $content = $(this.options.pulldownId).find('.ast-content');
  $('<p />').text('We have found 0 issues on the page !').appendTo($content);
};

CPDQMIssueRenderer.prototype.highlightIssueInPage = function(component){
  var $component = $('[data-as-id="' + component.componentId + '"]').first();

  if ($component.length) {

    var $wrapper = $component.find('.validation-output'),
      $ul = $wrapper.find('.activestandards-validation-list');

    if (!$wrapper.length) {

      $wrapper = $('<div class="validation-output">').appendTo($component);
      $ul = $('<ul class="activestandards-validation-list">').appendTo($wrapper);
    }

    var issueCount = component.checkpoints.length;
    for (var i = 0; i < issueCount; i++) {
      var issue = component.checkpoints[i],

        $a = $('<a />', {
          'title': issue.description
        }).text(issue.name);
      if (issue.sourceHighlightUrl) {
        $a.attr('href', issue.sourceHighlightUrl);
        $a.attr('target', '_blank');
        $a.addClass('js-ast-sh');
        $a.data('instances', issue.instances);
        $a.data('ref', issue.reference);
      }

      $('<li />').append($a).appendTo($ul);

    }

    $component.addClass('activestandards-validation activestandards-error');
  }
};

CPDQMIssueRenderer.prototype.setSourceHighlightingHash = function(){
  var aMap = {};
  $('.js-ast-sh').each(function(){
    var $link = $(this);
    var ref = $link.data('ref');
    if(ref !== undefined){
      var index = aMap[ref];
      index = (index === undefined) ? 1 : index;

      var href = $link.attr('href') + '#' + index;
      $link.attr('href', href);

      var instances = $link.data('instances');
      instances = (instances === undefined) ? 1 : instances;
      aMap[ref] = index + instances;
    }
  });
};

// Issues = [] of checkpoints
CPDQMIssueRenderer.prototype.createIssuesListModule = function(issues, h3Text, showInstanceCount) {
  var $content = $(this.options.pulldownId).find('.ast-content'),

    $listWrapper = $('<div />', {
      'class': 'ast-list-wrapper'
    });

  $('<h3 />').text(h3Text).appendTo($listWrapper);

  if (issues.length) {
    var $list = $('<ul />'),
      length = issues.length;
    for (var i = 0; i < length; i++) {
      var $li = $('<li />').append($('<span/>', {
        'class' : 'ast-list-text',
        'title' : issues[i].name
      }).text(issues[i].name));

      if (issues[i].sourceHighlightUrl) {
        var $span = $('<span />', {
          'class' : 'ast-list-inspect'
        });

          $('<a />', {
            'title': 'Inspect',
            'target': '_blank',
            'href': issues[i].sourceHighlightUrl
          }).text('Inspect').appendTo($span);
        $span.appendTo($li);
      }

      if(showInstanceCount){
        $li.append($('<span />', {
          'class': 'ast-list-count'
        }).text('(x' + issues[i].instanceCount + ')'));
      }

      $li.appendTo($list);
    }
    $list.appendTo($listWrapper);
  } else {
    $('<p />').text('No other issues were found').appendTo($listWrapper);
  }

  $listWrapper.appendTo($content);
};

window.cpdqmIssueRenderer = window.cpdqmIssueRenderer || new CPDQMIssueRenderer();

})( $CQ, window, document );