# nlフィルタ定義(文字コード判定用なのでこの行は削除しないこと)
# 17/04/14

#-----------------------------------------------------------------------------------------
[Replace]
Name = キャッシュ済動画のリンク色変更(watch)
URL = (?:www|news)\.nicovideo\.jp/watch/
Multi = TRUE
idGroup = 2
Match<
(href="(?:|/|http://www\.nicovideo\.jp/)watch/([a-z]{2}\d+)[^"]*"[^>]*)(>\s*)(?!<img|(?:一般|プレミアム)回線で視聴)
>
Replace<
$1 style="color:#<C00000$C08000>;"$3
>

#-----------------------------------------------------------------------------------------
# watchページのURLをリンク化
[Replace]
Name = watchURLtoLink
URL = www\.nicovideo\.jp/watch/
Multi = TRUE
Match<
(?i)h?(ttps?://[a-z0-9:./?!&\-~#=_%;+]+)(?![^<>]*>|[^<>]*</(?:a|textarea|script)>)
>
Replace<
<a href="h$1" target="_blank">$0</a>
>

#----------------------------------------------------------------------------------------
[Style]
Name = キャッシュアイコン位置(watchページ HTML5)
URL = www\.nicovideo\.jp/watch/
Require = "js-initial-watch-data"
Append<
	.PlaylistItemContent .cacheIcon { bottom:4px;}
	.PlaylistItemContent .cacheInfo {
		position:absolute; bottom:0px; padding:0 4px 0 4px; background-color:rgba(0,0,0,.6); color:white;
	}
>

#-----------------------------------------------------------------------------------------
[Script]
Name = javascript埋め込み(watchページ HTML5)
URL = www\.nicovideo\.jp/watch/
Require = "js-initial-watch-data"
Append<
document.addEventListener("DOMContentLoaded", function(){
 "use strict";

/* watchページ 再生リスト のキャッシュアイコンの表示＆色変え＆進捗表示 */
const
  $XHR = function(aUrl, resolve) {
    var httpObj = NicoCache_nl.xhr();
    httpObj.open('GET', aUrl, true);
    httpObj.onload = function() { resolve(httpObj); };
    // httpObj.onerror = function() { reject(httpObj.error); };
    httpObj.send();
  }
  ,updateInfo = function(aPlaylistCardItem, smid) {
    var aRouterLink = aPlaylistCardItem.getElementsByClassName('RouterLink')[0];
    aRouterLink.getElementsByClassName('PlaylistItemContent-playTime')[0]
      .insertAdjacentHTML("afterEnd", '<span class="cacheInfo"></span>');
    var cacheIcon = aRouterLink.getElementsByClassName('cacheIcon')[0];
    if (cacheIcon) cacheIcon.parentElement.removeChild(cacheIcon);
    var info = aRouterLink.getElementsByClassName('cacheInfo')[0];
    
    var cachingId, cacheId;
    var timer = setInterval(function() {
      if (!aPlaylistCardItem.classList.contains("is-playing")) {
        // 動画が切り替えられた
        info.parentElement.removeChild(info);
        clearInterval(timer);
        return;
      }
      $XHR('/cache/info/v2?' + smid, function(resp) {
        if (resp.status != 200) { clearInterval(timer); return; }
        var json = JSON.parse(resp.responseText);
        if (json[smid] == null) return;
        var caching = json[smid].cachings[0];
        if (caching == null) {
          if (cacheId == null) {
            cacheId = json[smid].preferredHTML5;
          }
          var cacheData = json[smid].caches[cacheId];
          if (!cacheData) return;
          if (!cacheData.complete) return;
          clearInterval(timer);
          setTimeout(function() {
            $XHR('/cache/info/v2?' + smid, function(resp) {
              var json = JSON.parse(resp.responseText);
              info.parentElement.removeChild(info);
              insertCacheIconItem(aRouterLink, json[smid].caches[cacheId]);
            });
          }, 1000);
        } else {
          if (cachingId != caching) {
            cachingId = caching;
            // cachdId = stripSrcId(cachingId)
            var m = caching.match(/^(\w+\[.*\])(?:\w+(\.\w+))?$/);
            if (m) {
              cacheId = m[1] + m[2];
            } else {
              cacheId = cachingId;
            }
          }
          var cacheData = json[smid].caches[cachingId];
          if (cacheData == null || cacheData.cachingSize == 0) return;
          
          var ratio = cacheData.cachingSize / cacheData.size;
          info.innerText = Math.floor(ratio * 100) + '%';
        }
      });
    }, 1000);
  }
  ,insertCacheIconItem = function(aRouterLink, cacheData) {
    if (!cacheData) return;
    if (aRouterLink.getElementsByClassName('cacheIcon').length) return;
   
    var
      cache = ''
      ,color = '';
    if (true /*!cacheData.dmc*/) {
      if (!cacheData.economy) {
        cache = 'cache';
        color = '#C00000';
      } else {
        cache = 'economy';
        color = '#C08000';
      }
    } else {
      if (!cacheData.economy) {
        cache = 'dmcCache';
        color = '#008000';
      } else {
        cache = 'dmcEconomy';
        color = '#808000';
      }
    }
    
    aRouterLink.getElementsByClassName('PlaylistItemContent-title')[0].style.color = color;
    aRouterLink.getElementsByClassName('PlaylistItemContent-thumbnail')[0].insertAdjacentHTML("afterEnd",
      '<div class="cacheIcon ' + cache + 'IconImgMin"></div>');
  }
  ,insertCacheIcons = function(PlaylistCardList) {
    var
      RouterLink = Array.from(PlaylistCardList[0].getElementsByClassName('RouterLink'))
      ,smids = RouterLink.map(function(E) { return E.getAttribute('href').split('/')[2] })
      ,F = function (aElem, json) {
        var
          smid = aElem.getAttribute('href').split('/')[2]
          ,smidData = (JSON.parse(json.responseText))[smid];
        if (!smidData) return;
        var cacheData = smidData.preferredHTML5 ? smidData.caches[smidData.preferredHTML5] : null;
        insertCacheIconItem(aElem, cacheData);
      };
    
    $XHR('/cache/info/v2?' + smids.join(','), function(json) {
      RouterLink.map(function(i) { return F(i, json) });
    });
  }
  ,init = function() {
    // キャッシュアイコン
    var PlaylistCardList = document.getElementsByClassName('PlaylistCardList');
    if(!PlaylistCardList.item(0)) return requestAnimationFrame(init);
    
    insertCacheIcons(PlaylistCardList);
    
    var observer = new MutationObserver(function (mutation) {
      insertCacheIcons(PlaylistCardList);
    });
    observer.observe(PlaylistCardList[0], {childList: true});
    
    // 進捗表示
    var F = function() {
      var playingCardItem = document.getElementsByClassName('PlaylistCardItem is-playing');
      if (!playingCardItem.item(0)) return;
      var playingRouterLink = playingCardItem[0].getElementsByClassName('RouterLink');
      if (!playingRouterLink.item(0)) return;
      var playingSmid = playingRouterLink[0].getAttribute('href').split('/')[2];
      updateInfo(playingCardItem[0], playingSmid);
      
      var observer = new MutationObserver(function(mutations) {
        for (var i in mutations) {
          if (mutations[i].oldValue.split(' ').indexOf("is-playing") >= 0 &&
              !mutations[i].target.classList.contains("is-playing")) {
            observer.disconnect();
            F();
          }
        }
      });
      observer.observe(playingCardItem[0],
          {attributes:true, attributeOldValue:true, attributeFilter:['class']});
    };
    F();
  };

init();

},false);
>

#-----------------------------------------------------------------------------------------
[Replace]
Name = キャッシュアイコンを追加(GINZA)
URL = www\.nicovideo\.jp/watch/
Require = res\.nimg\.jp/css/watch_zero/watch\.css\?
Multi = TRUE
EachLine = TRUE
Match<
(\s*)<img [^>]*class="(?:thumbnail|itemThumbnail)"\s*/?>
<img [^>]*class="itemImage"\s*/>
>
Replace<
$0$1<div class="cacheIcon"></div>
$0<div class="cacheIcon"></div>
>

#-----------------------------------------------------------------------------------------
[Style]
Name = キャッシュアイコンを定義(GINZA)
URL = www\.nicovideo\.jp/watch/
Require = res\.nimg\.jp/css/watch_zero/watch
Append<
	#playlistContainer .playlistItem .thumbContainer .cacheIcon,
	#videoExplorer .cacheIcon {
		position:absolute; top:auto; bottom:0px; left:0px; z-index:1000; display:none;
	}
	#playlistContainer .playlistItem .thumbContainer .cacheInfo {
		position:absolute; bottom:-8px; padding:0 4px 0 4px; background-color:rgba(0,0,0,.6); color:white;
	}
>

#-----------------------------------------------------------------------------------------
[Script]
Name = キャッシュアイコンを表示(GINZA)
URL = www\.nicovideo\.jp/watch/
Require = res\.nimg\.jp/js/watch/require
Append<
require([
	'jquery',
	'watchapp/init/PlaylistInitializer',
	'watchapp/init/VideoExplorerInitializer',
	'WatchJsApi'
], function($, PlaylistInitializer, VideoExplorerInitializer) {
	WatchJsApi.onInitialized(function() {
		var playlist = PlaylistInitializer.playlist;
		var playlistData = JSON.parse($('#playlistDataContainer').text());
		if (playlistData) {
			$(playlistData.playlist).each(function(index, data) {
				if (data.has_data) {
					var item = playlist.getItemByWatchID(data.id);
					if (item && item.id) {
						if (data.cache) {
							item.cache = data.cache
						} else if (item.id.match(/^[a-z]{2}[0-9]+$/)) {
							item.cache = 'none';
						}
					}
				}
			});
		}
		VideoExplorerInitializer.videoExplorer.addEventListener('refreshEnd', function (e) {
			setTimeout(function() {
				$(e.content.getItems()).each(function(index, item) {
					if (item._seed.cache) {
						showCacheIcon(item._id, item._seed.cache);
					}
				});
				$(e.content.getUadTagRelatedItemList()._items).each(function(index, item) {
					if (item._seed.cache) {
						showCacheIcon(item.getId(), item._seed.cache);
					}
				});
			}, 500);
		});
		WatchJsApi.player.addEventListener('onVideoInitialized', function() {
			var item = playlist.getPlayingItem();
			checkCached(item.id, function(cache) {
				if (cache != 'none') {
					item.cache = showCacheIcon(item.id, cache);
				} else {
					var info = $('<p class="cacheInfo"></p>');
					var index = playlist.getPlayingIndex();
					if (index >= 0) {
						var thumb = $('#playlistContainer ul.playlistItemList>li').eq(index)
								.find('.thumbContainer');
						thumb.find('.cacheIcon').hide();
						thumb.append(info);
					}
					var npc = PlayerApp.ns.player.Nicoplayer.getInstance()._nicoplayerConnector;
					var timer = setInterval(function() {
						var ratio = npc.getVideoBufferedRatio();
						info.text(Math.floor(ratio * 100) + '%');
						if (ratio == 1) {
							clearInterval(timer);
							setTimeout(function() {
								checkCached(item.id, function(cache) {
									info.remove();
									item.cache = showCacheIcon(item.id, cache);
								});
							}, 1000);
						}
					}, 1000);
				}
			});
		});
		$('#playlistContainer ul.playlistItemList').on('DOMNodeInserted', function(e) {
			var target = $(e.target);
			if (target.hasClass('playlistItem')) {
				var timer = setInterval(function() {
					var id = target.attr('data-nicowatch-video-id');
					if (id) {
						clearInterval(timer);
						var item = playlist.getItemByWatchID(id);
						if (item) {
							if (item.cache) {
								showCacheIcon(target, item.cache);
							}
						}
					}
				}, 50);
			}
		});
		function checkCached(id, callback) {
			var cache = 'none';
			$.get('/cache/info/v2?' + id, function(data) {
				var info = data[id];
				if (info != null && info.preferredFlash != null) {
					var cacheInfo = info.caches[info.preferredFlash];
					if (cacheInfo != null) {
						cache = (cacheInfo.economy ? 'economy' : 'cache');
					}
				}
				callback(cache);
			});
			
		}
	});
	function showCacheIcon(target, cache) {
		if (target) {
			if (typeof target === 'string') {
				target = $('a[href*="watch/' + target + '"]');
			}
			if (target.length > 0 && cache !== "none") {
				target.find('.cacheIcon').addClass(cache + "IconImgMin").show();
				target.find('span.title, span.videoTitle').css('color',
				    cache == 'cache' ? '#C00000':
				    cache == 'economy' ? '#C08000' : '#C00000');
			}
		}
		return cache;
	}
});
>
