// ==UserScript==
// @name        ShogiDB2 DownloadLinkCreator
// @description 将棋DB2の検索結果一覧ページに棋譜ダウンロードボタンを追加します。
// @include     https://shogidb2.com/latest*
// @include     https://shogidb2.com/floodgate*
// @include     https://shogidb2.com/tournament/*
// @include     https://shogidb2.com/player/*
// @include     https://shogidb2.com/strategy/*
// @require     https://cdn.rawgit.com/polygonplanet/encoding.js/master/encoding.min.js
// @namespace   knoa.jp
// @version     1.0
// ==/UserScript==
(function () {
  console.log('ShogiDB2 DownloadLinkCreator');
  var KEYWORDS = ['竜王戦','名人戦','順位戦','王位戦','王座戦','棋王戦','王将戦','棋聖戦'];/*対局情報に含まれていればハイライト*/
  var TITLES = ['竜王','名人','王位','王座','棋王','王将','棋聖','叡王','朝日杯','銀河','NHK杯','JT杯'];/*対局者名から取り除く称号*/
  var FILETYPE = 'KIF';/*棋譜ファイルの形式(CSA,KIF,KI2)*/
  var ENCODING = 'SJIS';/*棋譜ファイルの文字コード変換(SJIS,UTF8,...)※ブックマークレット実行時は無効*/
  var INTERVAL = 1000;/*短時間連続読み込みの抑制*/
  var LIMIT = 100;/*取得数制限(デバッグ用)*/
  var games = document.querySelectorAll('a.list-group-item');/*検索結果一覧*/
  var core = {
    /*初期化*/
    'initialize': function(){
      console.log('initialize...');
      var a, script;
      core.attatchStyle();
      a = document.createElement('a');
      a.className = 'make-downloads btn btn-primary';
      a.innerHTML = 'ダウンロードボタン生成';
      a.addEventListener('click', function(e){
        this.classList.add('disabled');
        /*棋譜データ処理スクリプトを取得してからボタン生成を始める*/
        script = document.createElement('script');
        script.src = '/js/shogiboard.min.js';
        script.addEventListener('load', function(e){
          core.createLink(0);
        });
        document.getElementsByTagName('head')[0].appendChild(script);
      });
      document.querySelector('h2').appendChild(a);
    },
    /*スタイル付与*/
    'attatchStyle': function(){
      console.log('attatchStyle...');
      var style, css = '';
      css += 'a.keywords{background:#ccddee!important;}';
      css += 'a.make-downloads{position:absolute;right:15px;}';
      css += 'a.download{position:absolute;right:30px;margin-top:-45px;}';
      style = document.createElement('style');
      style.innerHTML = css;
      document.getElementsByTagName('head')[0].appendChild(style);
      for(var i=0; games[i]; i++){
        if(games[i].innerText.match(new RegExp(KEYWORDS.join('|'))) != null){
          games[i].classList.add('keywords');
        }
      }
    },
    /*棋譜ダウンロードボタン生成*/
    'createLink': function (i) {
      console.log('createLink...', i);
      var a, xhr, d, table, date, title, sente, gote, kifu;
      /*無効状態のボタンを作っておく*/
      a = document.createElement('a');
      a.className = 'download btn btn-primary disabled';
      a.innerHTML = FILETYPE + '形式';
      games[i].parentNode.insertBefore(a, games[i].nextSibling);
      setTimeout(function () {
        xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function() {
          if (xhr.readyState == 4 && xhr.status == 200) {
            d = xhr.responseXML;
            /*ここからファイル名構築*/
            table = d.querySelector('table');
            date = table.querySelector('tr:nth-child(1) td').innerText.replace(/\b([1-9])(月|日)/g, '0$1$2');
            title = table.querySelector('tr:nth-child(2) td').innerText;
            sente = core.normalizeName(table.querySelector('tr:nth-child(4) td').innerText);
            gote = core.normalizeName(table.querySelector('tr:nth-child(5) td').innerText);
            a.download = [date, title, sente, gote].join('-') + '.' + FILETYPE.toLowerCase();
            /*ここから棋譜取得*/
            eval(d.querySelector('body>script[type]').innerText);/*"var data = {(json)}"であることを信頼*/
            kifu = core.exportKifu(data);
            /*ここからボタン有効化*/
            a.href = core.kifuToObjectURL(kifu);
            a.classList.remove('disabled');
          }
        };
        xhr.open('GET', games[i].href);
        xhr.responseType = 'document';
        xhr.send();
        if (!games[i+1] || LIMIT <= i+1){
          console.log('done.');
          return;
        }
        core.createLink(i+1);
      }, INTERVAL);
    },
    /*段位タイトルを削除*/
    'normalizeName': function(name){
      var dan = new RegExp('((女流|奨励会)?[初一二三四五六七八九・](級|段|冠)|' + TITLES.join('|') + ')$', 'g');
      name = name.replace(dan, '');
      name = name.replace(/ | /g, '');
      return name;
    },
    /*指定形式で棋譜ファイル生成*/
    'exportKifu': function(data){
      switch(FILETYPE){
        case 'CSA':
          return new CSAExporter(data).export();
        case 'KIF':
          return new KifExporter(data).export();
        case 'KI2':
          return new KI2Exporter(data).export();
      }
    },
    /*棋譜ファイルからobjectURL生成*/
    'kifuToObjectURL': function(kifu){
      var kifuArray;
      if(typeof Encoding === 'undefined' || ENCODING == 'UTF8'){
        kifuArray = [new Uint8Array([0xEF, 0xBB, 0xBF])/*BOM追加*/, kifu];
      }else{
        kifuArray = [new Uint8Array(Encoding.convert(kifu, {to:ENCODING, from:'AUTO', type:'array'}))];
      }
      return window.URL.createObjectURL(new Blob(kifuArray));
    }
  };
  core.initialize();
}) ();