/*______________________________________

  mizuyariTategaki #100211 [version 0.09]
  
  Copyright (C) 2009-2010 mizuyari All rights reserved.
  Script written by Mahiro Komura <mahirok@mizuyari.jp>
  http://mizuyari.jp/
______________________________________*/

var tategakiElements;
var tategakiCSS = "/shared/modules/mizuyari-tategaki/mizuyari-tategaki.css";
mizuyari.addCSS(tategakiCSS);
if (!d) var d = document;

function mizuyariTategakiInit() { // #090905
	for (var i=0; i<tategakiElements.length; i++) {
		tategakiElements[i].init();
	}
}

function mizuyariTategaki(element, id) { // #090905
	this.parentElmt = element;
	this.tategakiId = id;
	this.charsPerLine = 30;
	this.pageHeight = mizuyari.getElementHeight(this.parentElmt);
	this.baseImagePath = "/shared/modules/mizuyari-tategaki/images/";
	this.specialChars = "〈《「『【〔［｛（〉》」』】〕］｝）：；ー…‥～?―‐";
	this.suteganaChars = "ぁぃぅぇぉっゃゅょゎァィゥェォヵㇰヶㇱㇲッㇳㇴㇵㇶㇷㇷ゚ㇸㇹㇺャュョㇻㇼㇽㇾㇿヮ";
	this.backupInnerHTML = this.parentElmt.innerHTML;
    // this.mizFuncBench = new mizFuncBench();
}

mizuyariTategaki.prototype = {
	init : function() { // #090905
		if (this.locked) return;
		this.locked = true;
		this.lines = 0;
		this.cols = 0;
		this.currentPosX = 0;
		this.currentPosY = 0;
		this.lastPosX = 0;
		this.lastPosY = 0;
		
		this.currentNodeLines = 0;
		this.currentLineElements = [];
		
		this.tempRubyCount = 0;
		this.pages = 0;
		this.rubys = [];
		mizuyari.removeClass(this.parentElmt,'loaded');
		
		var loadingElmt = mizuyari.elementFactory('DIV',{
			'id'	: 'mizuyari-tategaki-loading' + this.tategakiId,
			'class' : 'mizuyari-tategaki-loading',
			'style' : 'text-align: center;'
		})
		var loadingImgElmt = mizuyari.elementFactory('IMG',{
			'src'	: (this.tategakiId%2 == 0) ? '/shared/modules/mizuyari-tategaki/images/loading.gif' :
				'/shared/modules/mizuyari-tategaki/images/loading2.gif',
			'alt' : '',
			'style' : 'width: 100px; height: 100px;'
		})
		if (this.parentElmt.innerHTML != this.backupInnerHTML) {
			this.parentElmt.innerHTML = this.backupInnerHTML;
		}
		loadingElmt.appendChild(loadingImgElmt);
		this.parentElmt.appendChild(loadingElmt);
		// this.finish();
		this.applyNewMarkup(this.parentElmt);
	},

	applyNewMarkup : function (node) { // #090905
		// trace("function: applyNewMarkup");
		if (!node) node = this.parentElmt;
		
		for (var i=0; i<node.childNodes.length; i++) {
			var currentNode = node.childNodes[i];
			if (currentNode.nodeType == 3) {
				if (currentNode.nodeValue.match(/ *\n$/)) continue;
				var newNodes = this.applySpanElmtToText(currentNode);

				// replaceNodes
				var j = 0;
				var nodesLength = newNodes.childNodes.length;
				while (newNodes.firstChild) {
						var vAlign = (mizuyari.containsClass(node, "author")) ? "bottom" : "top";
						node.insertBefore(newNodes.firstChild, currentNode);
						i++; j++;
				}

				node.removeChild(currentNode);
				i--;
			}
			if (currentNode.nodeType == 1) {
				/* ruby要素 */
				if (currentNode.nodeName == "RUBY") {
					var rubyId = (this.rubys.length) ? this.rubys.length : 0;
					// if (currentNode.id == "") currentNode.id = "ruby_" + rubyId;
					var newRuby = {
							"self" : currentNode,
							"RB" : (mizuyari.ua.isWinIE) ? currentNode.getElementsByTagName("RB")[0].nextSibling.nodeValue.length :
											currentNode.getElementsByTagName("RB")[0].childNodes[0].length,
							"RT" : currentNode.getElementsByTagName("RT")[0].childNodes[0].length
					}
					this.rubys[this.rubys.length] = newRuby;
				}

				if (currentNode.hasChildNodes) this.applyNewMarkup(currentNode);
			}
		}

		if (node == this.parentElmt) {
			setTimeout('tategakiElements['+ this.tategakiId +'].applyNewStyle()', 1000);
		}
	},

	applyNewStyle : function (node) { // #090905
		// trace("function: applyNewStyle");
		if (!node) node = this.parentElmt;
		var isBlockElmt = (mizuyari.getStyleProperty(node,'display') == 'block') ? true : false;
		
		if (node.nodeName != "SPAN" && isBlockElmt) {			
			this.currentPosX += mizuyari.getStyleProperty(node,'paddingRight');
			this.currentPosY = 0;
		}

		for (var i=0; i<node.childNodes.length; i++) {
			var currentNode = node.childNodes[i];

			if (currentNode.nodeType == 1) {
				if (currentNode.nodeName == "BR" &&
					(this.cols != 0 || this.cols >= this.charsPerLine-1)) this.lineBreak(currentNode);

				if (currentNode.nodeName == "SPAN") {
					if (node.nodeName == "RT") {
						var tempRuby = this.rubys[this.tempRubyCount-1];
						// if (i==0) trace(tempRuby);
						this.setTategakiRubyCharPosition(currentNode, i, node.childNodes.length, tempRuby);
					} else {
						this.setTategakiCharPosition(currentNode, i, node.childNodes.length);
					}
				}

				/* ruby */
				if (currentNode.nodeName == "RUBY") {
					this.tempRubyCount++;
				}

				if (currentNode.nodeName == "RP") {
						currentNode.style.display = "none";
						continue;
				}

				if (currentNode.hasChildNodes) this.applyNewStyle(currentNode);
			}
	
		}
 
		// 要素のおわり
		if (node.nodeName != "SPAN" && isBlockElmt && node.id != 'mizuyari-tategaki-loading'+this.tategakiId) {
			this.currentPosX += mizuyari.getStyleProperty(node,'paddingLeft');
			this.lineBreak(node);
		}

		if (node == this.parentElmt) {
			this.finish();
		}

	},
	
	finish : function () {
			// this.parentElmt.removeChild(miz$('mizuyari-tategaki-loading'+this.tategakiId));
			mizuyari.addClass(this.parentElmt, 'loaded');
			miz$('mizuyari-tategaki-loading'+this.tategakiId).style.display = 'none';
			this.locked = false;
			// trace(this.mizFuncBench.finish());		
	},

	setTategakiRubyCharPosition : function (element, charIndex, totalNodes, tempRuby) { // #090905
		var char;
		if (element.firstChild.nodeName == "IMG") {
			char = element.firstChild.alt;
		} else {
			char = (mizuyari.ua.isWinIE) ? element.innerText : element.textContent;
		}

		// ルビの位置補正

		if (!mizuyari.ua.isWinIE) {
			var RBElmt = tempRuby.self.getElementsByTagName("RB")[0];
			var RBPosY = RBElmt.firstChild.offsetTop;
			var rubyFixedHeight = Math.floor(getWordHeight(RBElmt) - tempRuby.RT * element.clientHeight) / 2;
		} else {
			var getWordHeight = 0;
			for (var i=0; i<tempRuby.self.getElementsByTagName('SPAN').length; i++) {
				var node = tempRuby.self.getElementsByTagName('SPAN')[i];
				if (node.parentNode.tagName != "RUBY") continue;
				getWordHeight += node.clientHeight;
			}
			var rubyFixedHeight = Math.floor(getWordHeight - tempRuby.RT * element.clientHeight) / 2;
			var RBPosY = tempRuby.self.getElementsByTagName('SPAN')[0].offsetTop;
		}


		element.style.top = (RBPosY + charIndex * element.clientHeight + rubyFixedHeight) + 'px';
		element.style.right = (this.lastPosX - element.clientWidth) + 'px';
		
		function getWordHeight(elmt) {
			// elmt は RB でなければいけない
			// if (elmt.tagName != "RB") return 0;
			var wordHeight = 0;
			for (var i=0; i<elmt.childNodes.length; i++) {
				wordHeight += elmt.childNodes[i].clientHeight;
			}
			return wordHeight;
		}			
	},

	setTategakiCharPosition : function (element, charIndex, totalNodes) { // #100211

		var char;
		var offsetPosX = 0, offsetPosY = 0;
		
		this.currentLineElements[this.currentLineElements.length] = element;
		
		if (element.firstChild.nodeName == "IMG") {
			char = element.firstChild.alt;
		} else {
			char = (mizuyari.ua.isWinIE) ? element.innerText : element.textContent;
		}
		if (char == "。" || char == "、") mizuyari.addClass(element, "punctuation");

		// trace(char + " / charIndex:" + charIndex + 'totalNodes' + totalNodes);

		// 縦書き文字変換処理
		if (this.specialChars.indexOf(char) != -1) mizuyari.addClass(element, "rotate90");
		
		// インデント処理（暫定）
		if (!mizuyari.ua.isWinIE && charIndex == 0) {
			var currentTextIndent = mizuyari.getStyleProperty(element.parentNode, 'marginTop');
			this.currentPosY += Math.ceil(currentTextIndent);
		}

		// 捨て仮名位置補正処理
		if (this.suteganaChars.indexOf(char) != -1) {
			var parentElmtFontSize = mizuyari.getFontSizeProperty(element.parentNode);
			offsetPosX -= Math.ceil(parentElmtFontSize * 0.15);
			offsetPosY -= Math.ceil(parentElmtFontSize * 0.07);
		}

		// 行頭禁則文字処理
		if (!charIndex == 0 && this.cols == 0 && this.isKinsokuTop(char)) {
			if (this.lines == 0) {
				this.pages--; this.lines = this.charsPerLine-1;
			} else {
				this.lines--;
			}
			this.cols = this.charsPerLine;
			this.currentPosY = this.lastPosY;
			this.currentPosX = this.lastPosX;
		}
		// 行末禁則文字処理
		if (this.cols == this.charsPerLine-1 && this.isKinsokuBottom(char)) {
			this.lineBreak();
		}

		element.style.top   = eval(this.currentPosY + offsetPosY) + 'px';
		element.style.right = eval(this.currentPosX + offsetPosX) + 'px';

		// element.id = "ln_" + this.lines + "col_" + this.cols;

		var currentElmtFontSize = mizuyari.getFontSizeProperty(element);
		var currentElmtLetterSpacing = mizuyari.getStyleProperty(element,'paddingBottom');
		this.setPosBy(null, currentElmtFontSize + currentElmtLetterSpacing);
		this.cols++;

		// IE だと element.lineHeight へのアクセスが遅すぎるので currentElmtFontSize を流用してみる (0.09)
		if (this.currentPosY + currentElmtFontSize > this.pageHeight) {
			if (charIndex != totalNodes -1) this.lineBreak(element);
		}

	},

	lineBreak : function (element) { // #090919
		this.applyAlign(element);
		var parentElmtLineHeight = mizuyari.getStyleProperty(element.parentNode,'lineHeight');
		this.lines++; this.cols=0;
		this.setPosTo(this.currentPosX + parentElmtLineHeight, 0);
		this.currentLineElements = [];
		// trace ("currentPosX: " + this.currentPosX);
		if (this.lines >= this.charsPerLine) { this.nextPage(); }
	},

	applyAlign : function(element) { // #090919
		if (mizuyari.containsClass(element, 'vAlignMiddle')) {
			this.applyAlignMiddle();
		} else if (mizuyari.containsClass(element, 'vAlignBottom')) {
			this.applyAlignBottom();
		}
	},
	applyAlignMiddle : function() { // #100211
		for (var i=0, j=this.currentLineElements.length; i<j; i++) {
				this.currentLineElements[i].style.top = 
				(this.pageHeight - this.currentPosY) / 2 + 
				parseInt(this.currentLineElements[i].style.top) + 'px';
		}
	},
	applyAlignBottom : function() { // #100211
		for (var i=0, j=this.currentLineElements.length; i<j; i++) {
				this.currentLineElements[i].style.top = 
				this.pageHeight - this.currentPosY + 
				parseInt(this.currentLineElements[i].style.top) + 'px';
		}
	},

	// posX, posY とも指定しない場合は null
	setPosTo : function(posX, posY) { // #090905
		this.lastPosX = this.currentPosX;
		this.lastPosY = this.currentPosY;
		if (posX != null) this.currentPosX = parseInt(posX);
		if (posY != null) this.currentPosY = parseInt(posY);
	},

	setPosBy : function(posX, posY) { // #090905
		this.lastPosX = this.currentPosX;
		this.lastPosY = this.currentPosY;
		if (posX != null) this.currentPosX += parseInt(posX);
		if (posY != null) this.currentPosY += parseInt(posY);
	},

	isKinsokuBottom : function (char) { // #090302b
			var kinsokuBottomChars = "‘“〈《「『【〔［｛（";
			return kinsokuBottomChars.indexOf(char) != -1;
	},
	isKinsokuTop : function (char) { // #090302b
			var kinzokuTopChars = "’”、。〉》」』】〕］｝）ゝゞヽヾ々・：；！？ー　";
			return kinzokuTopChars.indexOf(char) != -1;
	},

	shitayose : function () { // #090302b
	},

	nextPage : function () { // #090302b
			this.pages++;
			this.lines = 0;
	},

	applySpanElmtToText : function (textNode) { // #090302b
			var container = mizuyari.elementFactory("DIV");
			var textArray = textNode.nodeValue.split("");
			textArray.remove("\n");
			for (var i=0; i<textArray.length; i++) {
			textArray[i] = this.markupChar(textArray[i]);
			}
			container.innerHTML = textArray.join("");
			return container;
	},
	
	markupChar : function(char) { // #100211
			if (this.specialChars.indexOf(char) != -1) {
					return (mizuyari.ua.isFirefox && typeof(Worker) != "undefined" ||
					mizuyari.ua.isKHTML && d.compatMode || mizuyari.ua.isWinIE80 || mizuyari.ua.isWinIE60) ?
							'<span>' + char + '<\/span>' :
							'<span><img src="' + this.baseImagePath + 'chars/' + 
							EscapeUnicode(char).substring(1) + '.png" alt="' + char + '" /><\/span>';
			}
			return '<span>' + char + '<\/span>';
	}

}

mizuyari.addEvent(window,"load",function() {
	tategakiElements = getElementsByClassName('mizuyari-tategaki');
	for (var i=0; i<tategakiElements.length; i++) {
			tategakiElements[i] = new mizuyariTategaki(tategakiElements[i], i);
	}
	mizuyariTategakiInit();
});
// mizuyari.addOnLoadEvent(mizuyariTategakiInit);