﻿$(document).ready(function(){init();});

var init = function() {
	$('.reader').each(function() {
		this.Reader = new Reader(this);
	});
};

var Reader = function(parent) {
	var i, j, k;
	var self = this;
	var width = 640;
	var height = 480;
	var articles;
	var articleHeight = 48;
	var jqParent = $(parent);
		
	// getter
	self.getWidth = function() {
		return width;
	};
	self.getHeight = function() {
		return height;
	};
	self.getArticleHeight = function() {
		return articleHeight;
	};
	// setter
	
	// method
	var getShowCSS = function() {
		return {'opacity':'1.0'};
	};
	var getHideCSS = function() {
		return {'opacity':'0.0'};
	};
	var getSizeCSS = function() {
		return {'width':width+'px', 'height':height+'px'};
	};
	var getDefaultCSS = function() {
		return {};
	};
	self.show = function(anim) {
		if ( anim ) {
			jqParent.animate(getShowCSS());
		} else {
			jqParent.css(getShowCSS());
		}
		
		return self;
	};
	self.hide = function(anim) {
		if ( anim ) {
			jqParent.animate(getHideCSS());
		} else {
			jqParent.css(getHideCSS());
		}
		
		return self;
	};
	self.resize = function(w, h) {
		if ( typeof(w) !== 'undefined' ) {
			width = w;
		}
		if ( typeof(h) !== 'undefined' ) {
			height = h;
		}
		jqParent.css(getSizeCSS());
		
		return self;
	};
	self.init = function() {
		// set default css
		jqParent.css(getDefaultCSS());
		
		self.resize(0,0);
		self.hide();
		
		// TODO: 丁度良いサイズに変更
		width = Math.round( $(window).width()*0.5 );
		height = Math.round( $(window).height()*0.8 );
		self.resize();
		
		var headerHTML = document.createElement('div');
		headerHTML.className = 'header';
		jqParent.append(headerHTML);
		
		// add articles
		var articlesHTML = document.createElement('div');
		articles = new Articles(articlesHTML, self);
		jqParent.append(articlesHTML);
		
		var controllerLabel = document.createElement('div');
		$(controllerLabel)
			.empty()
			.append('SortBy -> ')
			.addClass('controller').addClass('label');
		
		var controllerIn = function() {
			$(this).addClass('hover');
		};
		var controllerOut = function() {
			$(this).removeClass('hover');
		};
		
		var controller1 = document.createElement('div');
		$(controller1)
			.empty()
			.append('Random')
			.unbind('click')
			.addClass('controller')
			.hover(controllerIn, controllerOut)
			.click(function() {articles.sortByRandom(true);});
		
		var controller2 = document.createElement('div');
		$(controller2)
			.empty()
			.append('ID')
			.unbind('click')
			.addClass('controller')
			.hover(controllerIn, controllerOut)
			.click(function() {articles.sortByID(true);});
		
		var controller3 = document.createElement('div');
		$(controller3)
			.empty()
			.append('Title')
			.unbind('click')
			.addClass('controller')
			.hover(controllerIn, controllerOut)
			.click(function() {articles.sortByTitle(true);});
		
		var clearLeft = document.createElement('div');
		$(clearLeft).css({'clear':'left'});

		
		$(headerHTML).append(controllerLabel);
		$(headerHTML).append(controller1);
		$(headerHTML).append(controller2);
		$(headerHTML).append(controller3);
		$(headerHTML).append(clearLeft);
		
		var url = jqParent.attr('title');
		$.ajax({
			'type'		: 'GET',
			'url'		: url,
			'dataType'	: 'xml',
			'success'	: init2
		});

		return self;
	};
	var init2 = function(xml) {
		articles.setArticleList(xml);
		articles.init();
		
		// test
		articles.changeListMode();
		self.resize();
		self.show(true);

	};
	
	self.init();
	return self;
};
var Articles = function(parent, reader) {
	var i,j,k;
	var self = this;
	var articles = new Array();
	var listModeNumber = Math.floor( reader.getHeight()/reader.getArticleHeight());
	var listModeOffset = 0;
	var detailCurrent = 0;
	var detailHeight = 3;
	var jqParent = $(parent);
	var lastSortType = 'id';
		
	// getter
	// setter
	
	var sort = function(comparator) { return function(anim) {
		var revFlag = false;	
		if ( comparator == orderByTitle ) {
			if ( lastSortType == 'title' ) {
				revFlag = true;
				lastSortType = 'titleRev';
			} else {
				lastSortType = 'title';
			}
		} else if ( comparator == orderByID ) {
			if ( lastSortType == 'id' ) {
				revFlag = true;
				lastSortType = 'idRev';
			} else {
				lastSortType = 'id';
			}
		} else if ( comparator == orderByRandom ) {
			if ( lastSortType == 'random' ) {
				revFlag = true;
				lastSortType = 'random';
			} else {
				lastSortType = 'random';
			}
		}
		
		var tmp;
		var i;
		var ii;
		var j;
		var jj;
		
		for ( ii = 0; ii < articles.length; ii++ ) {
			for ( jj = 0; jj < articles.length; jj++ ) {
				i = Math.min(ii,jj);
				j = Math.max(ii,jj);
				if ( revFlag ? !comparator( articles[i].Article, articles[j].Article ) : comparator( articles[i].Article, articles[j].Article ) ) {
					tmp = articles[i].Article.getPosition();
					articles[i].Article.setPosition( articles[j].Article.getPosition() );
					articles[j].Article.setPosition( tmp );
					tmp = articles[i];
					articles[i] = articles[j];
					articles[j] = tmp;
				}
			}
		}
		
		for ( i = 0; i < articles.length; i++ ) {
			articles[i].Article.changeListMode(anim);
		}
		
		return self;
	};};
	
	var orderByTitle = function(a,b) { return a.title > b.title; };
	var orderByID = function(a,b) { return parseInt(a.id) > parseInt(b.id); };
	var orderByRandom = function(a,n) { return parseInt(Math.random()*100)%2==0 };
	self.sortByTitle = sort(orderByTitle);
	self.sortByID = sort(orderByID);
	self.sortByRandom = sort(orderByRandom);
	
	self.changeListMode = function(anim) {
		for ( i = 0; i < articles.length; i++ ) {
			articles[i].Article.changeListMode(anim).setOffset(-listModeOffset).setPosition(i+1).show(anim).changeListMode(anim);
		}
		return self;
	};
	self.setDetailCurrent = function(_position) {
		detailCurrent = _position;
		return self;
	};
	self.changeDetailMode = function(anim) {
		var diff;
		for ( i = 0; i < articles.length; i++ ) {
			articles[i].Article.changeListMode(anim);
		}
		var upperNumber = Math.floor( ( listModeNumber - detailHeight ) / 2.0 );
		var lowerNumber = Math.ceil( ( listModeNumber - detailHeight ) / 2.0 );
		var absoluteOffset = 0;
		if ( detailCurrent - upperNumber <= 0 ) {
			absoluteOffset = detailCurrent - upperNumber - 1;
			lowerNumber += -absoluteOffset;
		} else if ( detailCurrent + lowerNumber > articles.length ) {
			upperNumber += detailCurrent + lowerNumber - articles.length;
		}
		if ( detailCurrent == 0 ) {
			listModeOffset = 0;
		}
		for ( i = 0; i < articles.length; i++ ) {
			diff = detailCurrent - articles[i].Article.getPosition();
			if ( diff >= 1 ) {
				if ( diff == upperNumber ) {
					listModeOffset = articles[i].Article.getPosition()-1;
				}
				articles[i].Article.setOffset(0).setAbsoluteOffset(absoluteOffset).setAbsolutePosition(1+upperNumber-diff).show(anim).changeListMode(anim);
			} else if ( diff == 0 ) {
				articles[i].Article.setOffset(0).setAbsoluteOffset(absoluteOffset).setAbsolutePosition(1+upperNumber).show(anim).changeDetailMode(anim);
			} else if ( diff <= -1 ) {
				articles[i].Article.setOffset(0).setAbsoluteOffset(absoluteOffset).setAbsolutePosition(1+upperNumber+detailHeight-diff-1).show(anim).changeListMode(anim);
			} else {
				if ( diff < 0 ) {
					articles[i].Article.setOffset(0).setAbsoluteOffset(absoluteOffset).setAbsolutePosition(5-diff).hide(anim).changeListMode(anim);
				} else {
					articles[i].Article.setOffset(0).setAbsoluteOffset(absoluteOffset).setAbsolutePosition(2-diff).hide(anim).changeListMode(anim);
				}
			}
		}
		return self;
	};
	self.getDetailHeight = function() {
		return detailHeight;
	};
	
	var getDefaultCSS = function() {
		return {
			'height':listModeNumber * reader.getArticleHeight(),
		};
	};
	
	self.init = function() {
		listModeOffset = 0;
		jqParent
			.addClass('articles')
			.css(getDefaultCSS());
	};

	var getArticle = function(element, data) {
		var article = new Article(element, reader);
		article['articles'] = self;
		article['id'] = $(data).find('id:first').text();
		article['title'] = $(data).find('title:first').text();
		article['description'] = $(data).find('description:first').text();
		article['categories'] = (function(){
			var categories = new Array();
			$(data).find('categories:first').find('category').each(function(){
				if ( $(this).find('id:first').text() !== '' ) {
					categories.push({
						'id': $(this).find('id:first').text(),
						'name': $(this).find('name:first').text()
					});
				}
			});
			return categories;
		})();
		return article;
	};
	self.setArticleList = function(xml) {
		$(xml).find('article').each(function() {
			var article = document.createElement('div');
			article.Article = getArticle(article, this);
			articles.push( article );
		});
		
		for ( i = 0; i < articles.length; i++ ) {
			jqParent.append(articles[i]);
		}
		
		for ( i = 0; i < articles.length; i++ ) {
			articles[i].Article.setText(articles[i].Article.getHTML());
			articles[i].Article.setPosition(i+1);
		}
	};
	
	return this;
};

var Article = function(parent, reader) {
	var self = this;
	var i, j, k;
	var height = reader.getArticleHeight();
	var detailHeight = height * 3;
	var position = 0;
	var absolutePosition = 0;
	var absoluteOffset = 0;
	var offset = 0;
	var borderSize = 3;
	var margin = 3;
	var mode = 0;
	var modeTypes = 2;
	var paddingLeft = 9;
	var cssTop = 0;
	var cssLeft = 0;
	var animopt = {'queue':false};
	var jqParent = $(parent);
	
	// getter
	self.getHTML = function() {
		return self.id+':'+self.title;
	};
	self.getPosition = function() {
		return position;
	};
	// setter
	self.setText = function(text) {
		jqParent.empty().append(text)
		return self;
	};
	self.setAbsoluteOffset = function(_offset) {
		absoluteOffset = _offset;
		return self;
	};
	self.setAbsolutePosition = function(_position) {
		absolutePosition = _position;
		cssTop = (absolutePosition-1+absoluteOffset)*height;
		cssLeft = 0;
		return self;
	};
	self.setPosition = function(_position) {
		position = _position;
		cssTop = (position-1+offset)*height;
		cssLeft = 0;
		return self;
	};
	self.setOffset = function(_offset) {
		offset = _offset;
		return self;
	};
	
	self.changeMode = function() {
		if ( mode == 0 ) {
			self.changeListMode();
		} else if ( mode == 1 ) {
			self.changeDetailMode();
		}
	};
	self.changeListMode = function(anim) {
		mode = 0;
		if ( anim ) {
			jqParent
				.animate(getPositionCSS(), animopt)
				.animate(getListCSS(), animopt);
		} else {
			jqParent
				.css(getPositionCSS())
				.css(getListCSS());
		}
		jqParent
			.unbind('hover')
			.hover(self.hoverInEvent, self.hoverOutEvent)
			.unbind('click')
			.click(self.clickEvent);
		return self;
	};
	self.changeDetailMode = function(anim) {
		mode = 1;
		if ( anim ) {
			jqParent
				.animate(getPositionCSS(), animopt)
				.animate(getDetailCSS(), animopt);
		} else {
			jqParent
				.css(getPositionCSS())
				.css(getDetailCSS());
		}
		jqParent
			.unbind('hover')
			.hover(self.hoverInEventDetail, self.hoverOutEventDetail)
			.unbind('click')
			.click(self.clickEventDetail);
		return self;
	};
	
	var getShowCSS = function() {
		return {
			'opacity':'1.0'
		};
	};
	var getHideCSS = function() {
		return {
			'opacity':'0.0'
		};
	};
	var getPositionCSS = function() {
		return {'top':cssTop+'px', 'left':cssLeft+'px'};
	};
	var getDefaultCSS = function() {
		return {
			'borderSize':borderSize+'px',
			'margin':margin+'px 0px',
			'fontSize':'24px',
		};
	};
	var getRealWidth = function(w) {
		return w-borderSize*2-paddingLeft;
	};
	var getRealHeight = function(h) {
		return h-borderSize*2-margin*2;
	};
	var getListCSS = function() {
		return {
			'width':getRealWidth(reader.getWidth())+'px',
			'height':getRealHeight(height)+'px',
			'paddingLeft':paddingLeft+'px',
			'lineHeight':getRealHeight(height)+'px',
			'left':cssLeft+'px',
			'top':cssTop+'px',
		};
	};
	var getDetailCSS = function() {
		return {
			'width':getRealWidth(reader.getWidth())+'px',
			'height':getRealHeight(self.articles.getDetailHeight()*height)+'px',
			'paddingLeft':paddingLeft+'px',
			'lineHeight':getRealHeight(detailHeight)+'px',
			'left':cssLeft+'px',
			'top':cssTop+'px',

		};
	};
	self.show = function(anim) {
		if ( anim ) {
			jqParent.animate(getShowCSS(), animopt);
		} else {
			jqParent.css(getShowCSS());
		}
		return self;
	};
	self.hide = function(anim) {
		if ( anim ) {
			jqParent.animate(getHideCSS(), animopt);
		} else {
			jqParent.css(getHideCSS());
		}
		return self;
	};
	// events
	self.clickEvent = function() {
		this.Article.articles.setDetailCurrent(this.Article.getPosition()).changeDetailMode(true);
		return false;
	};
	self.hoverInEvent = function() {
		jqParent.addClass('hover');
	};
	self.hoverOutEvent = function() {
		jqParent.removeClass('hover');
	};
	self.clickEventDetail = function() {
		this.Article.articles.changeListMode(true);
		return false;
	};
	self.hoverInEventDetail = function() {
		jqParent.addClass('hover');
	};
	self.hoverOutEventDetail = function() {
		jqParent.removeClass('hover');
	};

	self.init = function() {
		jqParent.css( getDefaultCSS() );
		jqParent.css( getListCSS() );
		jqParent.addClass('article');
		jqParent.empty();
		return self;
	};
	
	self.init();
	return self;
};



