(function ($) {
  'use strict';

  function escHtml(str) {
    return String(str)
      .replace(/&/g, '&amp;')
      .replace(/</g, '&lt;')
      .replace(/>/g, '&gt;')
      .replace(/"/g, '&quot;')
      .replace(/'/g, '&#039;');
  }

  function pct(score) {
    var n = 0;
    if (typeof score === 'number' && isFinite(score)) {
      n = score;
    }
    if (n < 0) n = 0;
    if (n > 1) n = 1;
    return Math.round(n * 100) + '%';
  }

  function ensureSuggestRow($tr, id) {
    var $next = $tr.next('tr.wpsn-404-suggest-row[data-id="' + id + '"]');
    if ($next.length) {
      return $next;
    }

    var colspan = $tr.children('td').length || 1;
    var $row = $('<tr class="wpsn-404-suggest-row" data-id="' + escHtml(id) + '"><td colspan="' + colspan + '"></td></tr>');
    $tr.after($row);
    return $row;
  }

  function renderLoading($row) {
    var msg = (window.WPSN404Suggest && WPSN404Suggest.i18n && WPSN404Suggest.i18n.loading) ? WPSN404Suggest.i18n.loading : 'Loading…';
    $row.find('td').html('<em>' + escHtml(msg) + '</em>');
  }

  function renderError($row, fallbackUrl, status) {
    var i18n = (window.WPSN404Suggest && WPSN404Suggest.i18n) ? WPSN404Suggest.i18n : {};
    var msg = i18n.error || 'Error';
    var busy = i18n.busy_503 || 'Server busy (503).';
    var openFallback = i18n.open_fallback || 'Open suggestions (no AJAX)';

    var text = (status === 503) ? busy : msg;

    var html = '';
    html += '<div style="color:#b32d2e;">' + escHtml(text) + '</div>';

    if (fallbackUrl && typeof fallbackUrl === 'string' && fallbackUrl !== '#' && fallbackUrl.indexOf('page=wpsn-404-monitor') !== -1) {
      html += '<div style="margin-top:8px;">';
      html += '<a class="button button-small" href="' + escHtml(fallbackUrl) + '">' + escHtml(openFallback) + '</a>';
      html += '</div>';
    }

    $row.find('td').html(html);
  }

  function renderEmpty($row) {
    var msg = (window.WPSN404Suggest && WPSN404Suggest.i18n && WPSN404Suggest.i18n.no_suggestions) ? WPSN404Suggest.i18n.no_suggestions : 'No suggestions.';
    $row.find('td').html('<em>' + escHtml(msg) + '</em>');
  }

  function renderSuggestions($row, suggestions) {
    var i18n = (window.WPSN404Suggest && WPSN404Suggest.i18n) ? WPSN404Suggest.i18n : {};

    var close = i18n.close || 'Close';
    var create301 = i18n.create_301 || 'Create 301';
    var prefillForm = i18n.prefill_form || 'Prefill form';
    var confidence = i18n.confidence || 'Confidence';

    var html = '';
    html += '<div style="margin: 6px 0 10px;">';
    html += '<strong>' + escHtml('Redirect suggestions') + '</strong>';
    html += ' <a href="#" class="wpsn-404-suggest-close" style="float:right;">' + escHtml(close) + '</a>';
    html += '</div>';

    html += '<table class="widefat striped" style="margin:0;">';
    html += '<thead><tr>';
    html += '<th>' + escHtml('To') + '</th>';
    html += '<th style="width: 110px;">' + escHtml(confidence) + '</th>';
    html += '<th>' + escHtml('Reason') + '</th>';
    html += '<th style="width: 240px;">' + escHtml('Actions') + '</th>';
    html += '</tr></thead><tbody>';

    for (var i = 0; i < suggestions.length; i++) {
      var s = suggestions[i] || {};
      var to = s.to || '';
      var label = s.label || '';
      var reason = s.reason || '';
      var score = s.score;
      var prefillUrl = s.prefill_url || '';
      var createUrl = s.create_url || '';

      html += '<tr>';
      html += '<td><code>' + escHtml(to) + '</code>';
      if (label) {
        html += '<div class="description" style="margin-top:4px;">' + escHtml(label) + '</div>';
      }
      html += '</td>';
      html += '<td>' + escHtml(pct(score)) + '</td>';
      html += '<td>' + escHtml(reason) + '</td>';
      html += '<td>';
      if (createUrl) {
        html += '<a class="button button-small" href="' + escHtml(createUrl) + '">' + escHtml(create301) + '</a> ';
      }
      if (prefillUrl) {
        html += '<a class="button button-small" href="' + escHtml(prefillUrl) + '">' + escHtml(prefillForm) + '</a>';
      }
      html += '</td>';
      html += '</tr>';
    }

    html += '</tbody></table>';

    $row.find('td').html(html);
  }

  $(document).on('click', 'a.wpsn-404-suggest', function (e) {
    e.preventDefault();

    var $link = $(this);
    var id = $link.data('id');
    var url = $link.data('url');
    var fallbackUrl = $link.attr('href') || '';

    var $tr = $link.closest('tr');
    if (!$tr.length) {
      return;
    }

    var $row = ensureSuggestRow($tr, id);

    // Toggle if already rendered.
    if ($row.data('loaded')) {
      $row.toggle();
      return;
    }

    renderLoading($row);

    $.ajax({
      method: 'POST',
      url: (window.WPSN404Suggest && WPSN404Suggest.ajaxUrl) ? WPSN404Suggest.ajaxUrl : ajaxurl,
      dataType: 'json',
      data: {
        action: 'wpsn_404_suggest_redirects',
        nonce: (window.WPSN404Suggest && WPSN404Suggest.nonce) ? WPSN404Suggest.nonce : '',
        id: id,
        url: url,
        // Where to redirect after creating a redirect from suggestion.
        // Must be validated server-side to prevent open redirects.
        back: (window.location && window.location.href) ? window.location.href : ''
      }
    }).done(function (resp) {
      if (!resp || !resp.success || !resp.data) {
        renderError($row, fallbackUrl, 0);
        return;
      }

      var suggestions = resp.data.suggestions || [];
      if (!suggestions.length) {
        renderEmpty($row);
        $row.data('loaded', true);
        return;
      }

      renderSuggestions($row, suggestions);
      $row.data('loaded', true);
    }).fail(function () {
      var status = 0;
      if (arguments && arguments.length && arguments[0] && typeof arguments[0].status === 'number') {
        status = arguments[0].status;
      }
      renderError($row, fallbackUrl, status);
    });
  });

  $(document).on('click', 'a.wpsn-404-suggest-close', function (e) {
    e.preventDefault();
    var $tr = $(this).closest('tr.wpsn-404-suggest-row');
    if ($tr.length) {
      $tr.hide();
    }
  });
})(jQuery);
