// ==UserScript==
// @name           wonderflTagSuggest
// @namespace      wonderfl.net
// @include        http://wonderfl.net/c/*
// ==/UserScript==
(function(){
	//p = unsafeWindow.console.log;
	
	//var isCodePage = /^http:\/\/wonderfl\.net\/c\/.+/.test(location.href);
    var button = document.getElementById('favorite_button');
	if(!button) return;
	
	var tagArea;
	//『お気に入りに追加』を押すと発動
    button.addEventListener('click', function(){
		var myTagsDiv = document.getElementById('my_tags_container');
        var delay = setInterval(function(){
            tagArea = myTagsDiv.getElementsByTagName('a');
			//tagAreaにタグが設定されるのを待つ
            if(tagArea.length > 0){
                clearInterval(delay);
                init(document.getElementById('tags'));
            }
         }, 1000 / 30);
    }, false);
    
    function init(tagInput){
		var isSuggesting = false;
		var prevInputword = undefined;
        var suggestBox = undefined;
		var selectedTagList = undefined;
        var index = 0;
		var tagLists = [];
		//browserデフォルトの補完windowが出るのを止める
        tagInput.setAttribute('autocomplete', 'off');
        
        function makeSuggestBox(){
            suggestBox = document.createElement('suggestBox');
            
            with (suggestBox.style) {
                border = '1px solid #CCC';
                position = 'absolute';
                background = '#FFF';
                zIndex = 1;
            }
            
            var n = tagArea.length;
            for (var i = 0; i < n; ++i) {
                var tag = tagArea[i].textContent;
                
                var li = document.createElement('li');
				with (li.style) {
					listStyleType = 'none';
					display = 'none';
					padding = '0 5px';
				}
				li.textContent = tag;
                
                tagLists.push(li);
                suggestBox.appendChild(li);
            }
            
            var parent = tagInput.parentNode;
            parent.style.position = 'relative';
            parent.insertBefore(suggestBox, tagInput.nextSibling);
        }
        makeSuggestBox();
		
		//現在表示されているサジェストワードのli要素を求める
		function getVisibleLists(){
			var visibleList = [];
            var n = tagLists.length;
            for (var i = 0; i < n; ++i) {
                var tagLi = tagLists[i];
                if (tagLi.style.display == 'block') {
                    visibleList.push(tagLi);
                }
            }
			return visibleList;
		}
        
		//ワード選択のハイライトを移動させる
        function select(_index){
			if(!isSuggesting) return;
			
            var visibleList = getVisibleLists();
            
            if (_index < 0) {
                index = visibleList.length - 1;
            }
			else if (_index > visibleList.length - 1) {
                index = 0;
            }
			else {
				index = _index;
			}
			
            selectedTagList = visibleList[index];
            var n = visibleList.length;
            for (var i = 0; i < n; ++i) {
                var li = visibleList[i];
				//選択中アイテムの外観
                if (li == selectedTagList) {
                    li.style.background = '#3366CC';
                    li.style.color = '#FFF'
                }
                else {
                    li.style.background = '#FFF';
                    li.style.color = '#000';
                }
            }
        }
        
        function hideSuggestBox(){
            suggestBox.style.display = 'none';
			isSuggesting = false;
        }
        
        function showSuggestBox(){
            suggestBox.style.display = 'block';
			isSuggesting = true;
        }
        
		//選択したサジェストワードを入力する
        function replaceToSuggestWord(){
            var selectedWord = selectedTagList.textContent;
            var insertPos = getSpaceBetweenCaret();
			
			var before = tagInput.value.slice(0, insertPos.start);
			var after = tagInput.value.slice(insertPos.end, tagInput.value.length);
			
            tagInput.value = before + selectedWord + after + ' ';
        }
		
		/**
		 * @return [キャレットがある位置から直前のワードが始まる位置、 キャレットがある位置]
		 * (スペース区切りでワードが入力されるのが前提) 
		 */
        function getSpaceBetweenCaret(){
            var n = tagInput.value.length;
            var lastSpaceNo = -1;
            for (var i = 0; i < tagInput.selectionStart; ++i) {
                if (tagInput.value.charAt(i) == ' ') {
                    lastSpaceNo = i;
                }
            }
            return {start:lastSpaceNo + 1, end:tagInput.selectionStart};
        }
        
		//キャレットの位置から、サジェスト対象になっている単語を特定する
        function getInpoutWord() {
            var string = tagInput.value;
            var insertPos = getSpaceBetweenCaret();
            var str = string.substring(insertPos.start, insertPos.end);
			/*
			if(insertPos.start !=0 && insertPos.start == insertPos.end){
				str = ' ';
			}
			*/
            return str;
        }
        
		//正規表現でマッチしたワードのみに絞り込んで表示する
        function narrowDownTo(suggestTargetString) {
            var regExp = new RegExp(suggestTargetString, 'i');
            var n = tagLists.length;
			//全てのタグから、正規表現でマッチするタグだけ表示させる
            for (var i = 0; i < n; ++i) {
                var tagLi = tagLists[i];
                if (regExp.test(tagLi.textContent)) {
                    tagLi.style.display = 'block';
                }
                else {
                    tagLi.style.display = 'none';
                }
            }
        }
        
        document.addEventListener("click", function(e){
            hideSuggestBox();
        }, false);
       
	   	//エンター、もしくはタブが押された時の処理
        tagInput.addEventListener("keydown", function(e){
			switch(e.keyCode) {
				case 13://13 enter, 9 tab
				case 9:
					if(isSuggesting){
						e.preventDefault();//イベントキャンセル
		                replaceToSuggestWord();
		                hideSuggestBox();
					}
				break;
				
				//キーリピートに対応させるために、keydowイベントで作動させる
				case 38://38 up arrow
					select(index - 1);
					//イベントキャンセル 先頭にキャレットが移動するのを防ぐ
					e.preventDefault();
				break;
				
				case 40://40 down arrow
					select(index + 1);
					//イベントキャンセル 末尾にキャレットが移動するのを防ぐ
					e.preventDefault();
				break;
			}
			
			prevInputword = tagInput.value;
			
        }, false);
        
        tagInput.addEventListener("keyup", function(e){
			switch(e.keyCode) {
				case 27://27 escape
					hideSuggestBox();
				break;
				
				case 16://shift
				case 17://ctrl
				case 18://alt
				case 37://38 left arrow
				case 38://38 up arrow
				case 39://38 right arrow
				case 40://40 down arrow
				break;
				
				default:
					//内容が変わっていなければ処理しない
					if(prevInputword == tagInput.value) break;
					
					var inputWord = getInpoutWord();
					//サジェストの絞り込み
					if(!inputWord) {
						hideSuggestBox();
					}
					else{
						narrowDownTo( inputWord );
						showSuggestBox();
						//先頭を選択した状態にする
		                select(0);
					}
				}
        }, false);
    }
})();
