// ? Bookmark Filter, released under the GPL
// http://www.gnu.org/copyleft/gpl.html
//
// ==UserScript==
// @name           Hatena Bookmark Filter
// @description    Allows users to hide bookmarks without any stars, comments, nor tags.
// @include        http://b.hatena.ne.jp/entry/*://*
// ==/UserScript==
//
// 2008-11-25 (v0.8) Added a new filter "Starred Comments" and modifications to support the new site design (http://hatena.g.hatena.ne.jp/hatenabookmark/20081125/1227602284).
// 2007-08-17 (v0.7) Added modifications to follow today's change (http://hatena.g.hatena.ne.jp/hatenabookmark/20070817/1187335133).
// 2007-06-08 (v0.6) Added modifications to follow today's change (http://hatena.g.hatena.ne.jp/hatenabookmark/20070608/1181284251).
// 2007-05-29 (v0.5) Added modifications to follow today's change (http://hatena.g.hatena.ne.jp/hatenabookmark/20070529/1180419718).
// 2006-05-01 (v0.4) Changed some behaviors to allow this tool to work properly with Hatena Comment Linker or on entry pages that have no bookmarks.
// 2006-03-20 (v0.3) Added modifications to follow today's change (http://hatena.g.hatena.ne.jp/hatenabookmark/20060320/1142826161).
// 2006-03-17 (v0.2) Added modifications to follow today's change (http://hatena.g.hatena.ne.jp/hatenabookmark/20060317/1142566819).
// 2006-02-16 (v0.1) Initial Version.

(function(){
  const FILTER_LEVELS = [ { name: 'filterNone',
                            path: 'true()',
                            text: '\u3059\u3079\u3066\u8868\u793a' },
                          { name: 'filterNoTagComment',
                            path: 'SPAN[@class="tags"]/A|SPAN[@class="comment"]/text()',
                            text: '\u30bf\u30b0+\u30b3\u30e1\u30f3\u30c8\u4e00\u89a7' },
                          { name: 'filterNoComment',
                            path: 'SPAN[@class="comment"]/text()',
                            text: '\u30b3\u30e1\u30f3\u30c8\u4e00\u89a7' },
                          { name: 'filterNoStar',
                            path: 'false()',
                            text: '\u30b9\u30bf\u30fc\u4e00\u89a7',
                            hook: function (e) {
                              location.href = 'javascript:' + function () {
                                var p = Hatena.Star.Entry.prototype;
                                p.__bindStarEntry = p.bindStarEntry;
                                p.bindStarEntry = function () {
                                  p.__bindStarEntry.apply(this, arguments);
                                  this.star_container.parentNode.className = this.star_container.parentNode.className.replace('filterNoStar', '');
                                };
                              }.toSource() + '()';
                            } } ];

  const container = document.getElementById('bookmarked_user');
  
  if (!container) {
    return;
  }
  
  GM_addStyle((function (v) {
    var s = [];
    for (var e in v) {
      s.push('body.' + v[e].name + ' li.' + v[e].name);
      v[e].path = document.createExpression(v[e].path, null)
    }
    return s.join(',');
  })(FILTER_LEVELS) + '{ display: none; } LABEL { cursor: pointer; padding: 0 4px; font-weight: normal; }');

  const options = document.evaluate('/descendant::H2[@class="comment bookmark-list"]/SPAN', document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  const entries = container.getElementsByTagName('LI');

  for (var i = 0; i < entries.length; ++i) {
    var e = entries[i];
    var v = [];
    for (var k in FILTER_LEVELS) {
      var fl = FILTER_LEVELS[k];
      if (!fl.path.evaluate(e, XPathResult.BOOLEAN_TYPE, null).booleanValue) {
        v.push(fl.name);
      }
    }
    e.className = v.join(' ');
  }
  
  for (var k in FILTER_LEVELS) {
    var fl = FILTER_LEVELS[k];
    if (fl.hook) {
      fl.hook.call(fl, entries);
    }
  }

  var initMode = GM_getValue('mode', 0);

  for (var i = 0; i < FILTER_LEVELS.length; ++i) {
    (function (mode) {
      var input = document.createElement('INPUT');
      input.type = 'radio';
      input.name = 'mode';
      input.checked = mode == initMode;
      input.addEventListener('click', (function (e) {
        if (input.checked) {
          GM_setValue('mode', mode);
          document.body.className = FILTER_LEVELS[mode].name;
        }
        return arguments.callee;
      })(null), false);
      
      var label = document.createElement('LABEL');
      label.appendChild(input);
      label.appendChild(document.createTextNode(FILTER_LEVELS[mode].text));
      
      options.appendChild(label);
    })(i);
  }
})()

