var Wordbreak = {
	flash_codebase: (Prototype.Browser.IE ? 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,0,0" ' : ''),
	
	resizeViewFrame: function(view_element) {
		$('ViewFrame').style.height = Math.max(document.viewport.getHeight() - ($('Top').visible() ? 83 : 0), 0) + 'px';
	},
	
	resizeTitle: function() {
		$('Title').style.width = Math.max(document.viewport.getWidth() - 230, 0) + 'px';
	},
	
	repositionViewElement: function(view_element) {
		var view_frame_height = parseInt($('ViewFrame').style.height);
		if (view_frame_height > 0)
		{
			view_element.style.height = '';
			var margin = view_frame_height - view_element.getHeight();
			view_element.setStyle(margin > 0 ? {'top': (margin / 2) + 'px'} : {'top': 0, 'height': view_frame_height + 'px'});
			$('ToggleMiniModeFloat').style.marginRight = (margin >= 0 ? 5 : 20) + 'px';
		}
	},
	
	playSound: function(type, url) {
		new PeriodicalExecuter(function() {
			try {
				switch (type)
				{
				default:
				case 'mp3':
					object_tag = '<object type="application/x-shockwave-flash" data="' + ROOT_URL + 'swf/wordbreak_mp3_player.swf" ' + Wordbreak.flash_codebase + 'width="0" height="0"><param name="movie" value="' + ROOT_URL + 'swf/wordbreak_mp3_player.swf" /><param name="AllowScriptAccess" value="always" /><param name="FlashVars" value="mp3=' + url + '&autoplay=1" /></object>';
					break;
					
				case 'wav':
					object_tag = '<object type="' + $H({'mp3': 'audio/mpeg', 'wav': 'audio/x-wav'}).get(type) + '" data="' + url + '" width="0" height="0"><param name="src" value="' + url + '" /><param name="autoplay" value="true" /><param name="autoStart" value="1" /><param name="volume" value="100" /></object>';
					break;
				}
				$('WordbreakMediaPlayerDiv').update(object_tag);
			} catch(e) {}
			this.stop();
		}, 0);
	},
	
	stopSound: function() {
		$('WordbreakMediaPlayerDiv').update('');
	},
	
	showImage: function(url) {
		$('PlayerViewImage').update('<img src="' + url + '" onload="Wordbreak.resizeImage(this);" />').show();
	},
	
	resizeImage: function(image) {
		var width = document.viewport.getWidth() * 0.7;
		if (image.width > width)
			image.width = width;
		Wordbreak.repositionViewElement($('PlayerView'));
	}
};

var Menu = {
	popup: function() {
		Event.observe(document, 'click', Menu.close);
	},
	
	close: function() {
		if ($('Menu') != undefined && !$('Menu').toggle().visible())
			Event.stopObserving(document, 'click', Menu.close);
	}
};

var Recorder = Class.create({
	initialize: function() {
		var rec = this;
		new PeriodicalExecuter(function() {
			rec.save();
		}, 60);
	},
	
	save: function() {
		new Ajax.Request(ROOT_URL + 'player/record');
	}
});

var App = Class.create({
	initialize: function(data_url) {
		this.data = new Data(this, data_url);
		this.config_data = new ConfigData(this);
		
		this.controller = null;
		this.player = new PlayerController(this);
		this.quiz = new QuizController(this);
		this.config = new ConfigController(this);
		
		this.setMode('player');
		
		var app = this;
		Event.observe(document.onresize ? document : window, 'resize', function() {
			app.onResize();
		});
		
		$$('a', 'input[type="radio"]').each(function(element) {
			Event.observe(element, 'focus', function() {
				this.blur();
			});
		});
		
		document.observe('keydown', function(event) { app.onKeyDown(event); });
		
		$('PopupMenu').observe('click', Menu.popup);
		$('PlaySound').observe('click', function() { app.onPlaySoundButtonClick(); });
		$('IncreaseFontSize').observe('click', function() { app.onIncreaseFontSizeButtonClick(); });
		$('DecreaseFontSize').observe('click', function() { app.onDecreaseFontSizeButtonClick(); });
		$('ToggleMiniMode').observe('click', function() { app.onToggleMiniModeButtonClick(); });
		
		$('ToggleMiniModeFloat').observe('click', function() { app.player.view.toggleMiniMode(); });
		
		$('MenuPlayer').observe('click', function() { app.setMode('player'); });
		$('MenuQuiz').observe('click', function() { app.setMode('quiz'); });
		$('MenuConfig').observe('click', function() { app.setMode('config'); });
		
		$('Prev').observe('mousedown', function() { app.player.onPositionButtonDown('prev'); });
		$('Prev').observe('mouseup', function() { app.player.onPositionButtonUp('prev'); });
		$('Prev').observe('mouseout', function() { app.player.onPositionButtonUp(); });
		
		$('Play').observe('click', function() { app.player.onPlayButtonClick(); });
		
		$('Next').observe('mousedown', function() { app.player.onPositionButtonDown('next'); });
		$('Next').observe('mouseup', function() { app.player.onPositionButtonUp('next'); });
		$('Next').observe('mouseout', function() { app.player.onPositionButtonUp(); });
		
		$('ToggleMode').observe('click', function() { app.player.toggleOrder(); });
		$('ToggleName').observe('click', function() { app.player.view.toggleName(); });
		$('ToggleMean').observe('click', function() { app.player.view.toggleMean(); });
		$('ToggleExample').observe('click', function() { app.player.view.toggleExample(); });
		$('Complete').observe('click', function() { app.player.onCompleteButtonClick(); });
		
		$('BtnQuizStart').observe('click', function() { app.quiz.start(); });
		
		$('Answer0').observe('click', function() { app.quiz.check(0); });
		$('Answer1').observe('click', function() { app.quiz.check(1); });
		$('Answer2').observe('click', function() { app.quiz.check(2); });
		$('Answer3').observe('click', function() { app.quiz.check(3); });
		$('BtnCheckQuestion').observe('click', function() { app.quiz.check(); });
		$('BtnNextQuestion').observe('click', function() { app.quiz.next(); });
		$('BtnQuizResult').observe('click', function() { app.quiz.result(); });
		
		$('BtnQuizHome').observe('click', function() { app.quiz.init(); });
		
		$('BtnConfigApply').observe('click', function() { app.config.apply(); });
		$('InputAlwaysOnTop').observe('click', function() { app.config.alwaysOnTop(); });
		
		Event.observe(window, 'unload', function() {
			if (app.recorder)
				app.recorder.save();
			// 학습창 크기 저장
		});
		
		this._initWordbreakHelper();
		
		this.data.load();
	},
	
	_initWordbreakHelper: function() {
		if (!Prototype.Browser.IE || WordbreakHelper.object == null)
			return;
		
		WordbreakHelper.PlayerMode = true;
		WordbreakHelper.AlwaysOnTop = this.config_data.always_on_top;
	},
	
	onResize: function() {
		Wordbreak.resizeTitle();
		Wordbreak.resizeViewFrame();
		this.controller.view.onResize();
	},
	
	setMode: function(type) {
		if (this.controller && !this.controller.close())
			return;
		this.controller = $H({'player': this.player, 'quiz': this.quiz, 'config': this.config}).get(type);
		this.controller.active();
	},
	
	onLoad: function() {
		this.config.onLoad();
		$('Title').update(this.data.title);
		if (this.data.access_status == 0 || this.data.access_status == 1)
			this.recorder = new Recorder();
		this.player.onLoad();
	},
	
	onLoadFailed: function() {
		this.player.onLoadFailed();
	},
	
	onPlaySoundButtonClick: function() {
		if (!$('PlaySound').hasClassName('Enable'))
			return;
		
		this.controller.sound.play();
	},
	
	onIncreaseFontSizeButtonClick: function() {
		if (!$('IncreaseFontSize').hasClassName('Enable'))
			return;
		
		this.controller.view.increaseFontSize();
	},
	
	onDecreaseFontSizeButtonClick: function() {
		if (!$('DecreaseFontSize').hasClassName('Enable'))
			return;
		
		this.controller.view.decreaseFontSize();
	},
	
	onToggleMiniModeButtonClick: function() {
		if (!$('ToggleMiniMode').hasClassName('Enable'))
			return;
		
		this.controller.view.toggleMiniMode();
	},
	
	onKeyDown: function(event) {
		this.controller.onKeyDown(event);
	}
});

var Controller = Class.create({
	initialize: function() {
		this.view = null;
	},
	
	onKeyDown: function(event) {
		
	},
	
	active: function() {
		if (this.view)
			this.view.show();
	},
	
	close: function() {
		if (this.view)
			this.view.hide();
		
		return true;
	}
});

var PlayerController = Class.create(Controller, {
	initialize: function(app) {
		this.app = app;
		
		this.view = new LoadingView(this);
		
		this.sound = new SoundPlugin(this);
		this.image = new ImagePlugin(this);
		this.style = new StylePlugin(this);
		
		this.order_type = 0;
		
		this.position = 0;
		
		this.is_playing = false;
	},
	
	onLoad: function() {
		this.view.hide();
		this.view = new PlayerView(this);
		this.view.show();

		if (this.app.config_data.sound_auto_play)
			this.sound.play();
		
		if (this.app.config_data.auto_play)
		{
			this._play();
			this.view.updatePlayButton();
		}
	},
	
	onLoadFailed: function() {
		this.load_status = -1;
		this.view.update();
	},
	
	onPlayButtonClick: function() {
		if (this.is_playing)
		{
			this._stop(true);
		}
		else
		{
			this._play();
			if (this.app.config_data.sound_auto_play)
				this.sound.play();
		}
		this.view.updatePlayButton();
	},
	
	onCompleteButtonClick: function() {
		this._complete();
	},
	
	_complete: function() {
		if (!this.app.data.book_id)
			return;
		
		if (this.app.data.access_status == 2)
		{
			alert('\'암기완료\' 기능을 사용하시려면, 로그인이 필요합니다.');
			return;
		}
		
		if (this.app.data.access_status == 1)
		{
			alert('자신의 학습장에만 \'암기완료\' 기능을 사용할 수 있습니다.\n\'학습장 스크랩\'기능을 사용해주세요.');
			return;
		}
			
		var idx = this.app.data.index[this.position];
		if (this.app.data.vocabs[idx][4])
			return;
		
		var is_playing = this.is_playing;
		if (is_playing)
			this._stop();
					
		var viid = this.app.data.deleteIndex(idx);
		new Ajax.Request(ROOT_URL + 'player/complete/' + this.app.data.book_id + '/' + viid);
		
		this._setPosition(this.position < this.app.data.count() ? this.position : 0);
		this.view.update();
		if (is_playing)
			this._play();
		if (this.app.config_data.sound_auto_play)
			this.sound.play();
	},
	
	_play: function() {
		if (!this.is_playing && this.app.data.count() > 0)
		{
			this.is_playing = true;
			
			this.countdown_number = this.app.config_data.delay_time;
			this._countdown();
			
			var player = this;
			this.countdown_timer = new PeriodicalExecuter(function() {
				if (player._countdown() < 1)
					player._next();
			}, 1);
		}
	},
	
	_stop: function(manual) {
		if (this.is_playing)
		{
			this.is_playing = false;
			
			if (manual && this.app.config_data.sound_auto_play)
				Wordbreak.stopSound();
			
			this.countdown_timer.stop();
			this.countdown_number = 0;
			this.view.updateCountdown();
		}
	},
	
	_next: function() {
		if (this.is_playing)
		{
			this._stop();
			this._play();
		}
		
		this._setPosition(this.position < this.app.data.count() - 1 ? this.position + 1 : 0);
		this.view.update();
		if (this.app.config_data.sound_auto_play)
			this.sound.play();
	},
	
	_prev: function() {
		if (this.is_playing)
		{
			this._stop();
			this._play();
		}
		
		this._setPosition(this.position > 0 ? this.position - 1 : this.app.data.count() - 1);
		this.view.update();
		if (this.app.config_data.sound_auto_play)
			this.sound.play();
	},
	
	_setPosition: function(position) {
		this.position = position;
	},
	
	onPositionButtonDown: function(type) {
		var controller = this;
		var timer_counter = 0;
		this.position_button_event_timer = new PeriodicalExecuter(function() {
			if (++timer_counter > 10)
			{
				switch (type)
				{
				case 'next':
					controller._next();
					break;
				case 'prev':
					controller._prev();
					break;
				}
			}
		}, 0.05);
	},
	
	onPositionButtonUp: function(type) {
		switch (type)
		{
		case 'next':
			this._next();
			break;
		case 'prev':
			this._prev();
			break;
		}
		
		if (this.position_button_event_timer)
			this.position_button_event_timer.stop();
	},
	
	_countdown: function() {
		this.countdown_number -= 1;
		this.view.updateCountdown();
		return this.countdown_number;
	},
	
	toggleOrder: function() {
		if (!this.app.data.isLoaded())
			return;
		
		this.order_type = (this.order_type + 1) % 3;
		this._order($A(['default', 'order', 'random'])[this.order_type]);
	},
	
	_order: function(type) {
		if (this.is_playing)
		{
			this._stop();
			this._play();
		}
		
		this.app.data.order(type);
		this.view.order(type);
		
		this._setPosition(0);
		this.view.update();
		if (this.app.config_data.sound_auto_play)
			this.sound.play();
	},
	
	onKeyDown: function(event) {
		var key = event.which || event.keyCode;
		
		switch (key)
		{
		case 32:
			this.onPlayButtonClick();
			break;
		case Event.KEY_LEFT: case 188: // '<'
			this._prev();
			break;
		case Event.KEY_RIGHT: case 190: // '>'
			this._next();
			break;
		case 48: case 96: // '0', NUM0
			this._complete();
			break;
		case 49: case 97: // '1', NUM1
			this.view.toggleName();
			break;
		case 50: case 98: // '2', NUM2
			this.view.toggleMean();
			break;
		case 51: case 99: // '3', NUM3
			this.view.toggleExample();
			break;
		case 52: case 100: // '4', NUM4
			this.view.toggleMeanExample();
			break;
		case Event.KEY_UP: 
			if (event.ctrlKey)
				this.view.increaseFontSize();
			break;
		case Event.KEY_DOWN:
			if (event.ctrlKey)
				this.view.decreaseFontSize();
			break;
		case 80: // 'P'
			this.sound.play();
			break;
		}
	},
	
	close: function($super) {
		this._stop(true);
		this.view.updatePlayButton();
		return $super();
	}
});

var QuizController = Class.create(Controller, {
	initialize: function(app) {
		this.app = app;
		
		this.quiz_type = 'name-mean';
		this.quiz_count = app.config_data.quiz_count;
		
		this.view = this.start_view = new QuizStartView(this);
		this.loading_view = new QuizLoadingView(this);
		this.result_view = new QuizResultView(this);
		this.quiz_view = new QuizView(this);
		
		this.position = 0;
		this.is_started = false;
		
		this.top_menu_status = [false, true, true, true];
	},
	
	init: function() {
		this.is_started = false;
		this.view.hide();
		this.view = this.start_view;
		this.view.show();
	},
	
	start: function() {
		var quiz_count = parseInt($F('InputQuizCount'));
		if (!Object.isNumber(quiz_count))
		{
			alert('퀴즈 개수를 입력해 주십시오.');
			return;
		}
		
		this.is_started = true;
		
		this.view.hide();
		this.view = this.loading_view;
		this.view.show();
		
		var quiz = this;
		new PeriodicalExecuter(function() {
			quiz.quiz_type = $('QuizTypeNameMean').checked ? 'name-mean' : 'mean-name';
			quiz.quiz_count = quiz.generateQuiz(quiz_count);
			quiz.position = 0;
			quiz.score = 0;
			quiz.question_status = 'active';
			
			quiz.view.hide();
			quiz.view = quiz.quiz_view;
			quiz.view.show();
			
			this.stop();
		}, 0);
	},
	
	generateQuiz: function(quiz_count) {
		var quiz = this;
		this.question_index = this.app.data.getRandomIndex().reject(function(idx) {
			return quiz.app.data.vocabs[idx][1].length == 0;
		});
		
		var quiz_count = Math.min(quiz_count, this.question_index.length);
		this.solutions = $A();
		this.answer_indexes = $A();
		for (var i = 0; i < quiz_count; ++i)
		{
			var question_idx = this.question_index[i];
			this.answer_indexes.push(this._generateAnswerIndex(question_idx));
		}
		
		return quiz_count;
	},
	
	_generateAnswerIndex: function(question_idx) {
		var vocabs = this.app.data.vocabs;
		
		var temp_index = this.question_index.reject(function(idx) {
			return vocabs[question_idx][0] == vocabs[idx][0] || vocabs[question_idx][1] == vocabs[idx][1];
		}).sort(function(a, b) {
			return Math.round(Math.random()) - 0.5;
		});
		
		var answer_index = $A();
		var count = 0;
		while (++count < 4 && temp_index.length > 0)
		{
			answer_index.push(temp_index[0]);
			temp_index = temp_index.reject(function (idx) {
				return (vocabs[temp_index[0]][0] == vocabs[idx][0] || vocabs[temp_index[0]][1] == vocabs[idx][1]);
			});
		}
		
		answer_index.push(question_idx);
		
		var idx = Math.floor(Math.random() * answer_index.length);
		answer_index[answer_index.length - 1] = answer_index[idx];
		answer_index[idx] = question_idx;
		this.solutions.push(idx);
		
		return answer_index;
	},
	
	check: function(answer_idx) {
		if (this.question_status == 'answered')
		{
			this.next();
			return;
		}
		
		this.question_status = 'answered';
		this.correct_answer = this.solutions[this.position];
		this.wrong_answer = answer_idx == undefined ? this.correct_answer : (answer_idx != this.correct_answer ? answer_idx : null);
		
		this.score += this.wrong_answer != null ? 0 : 1;
		
		this.view.update();
	},
	
	next: function() {
		if (this.position >= this.quiz_count - 1)
		{
			this.result();
			return;
		}
		
		this.question_status = 'active';
		this.position += 1;
		
		this.view.update();
	},
	
	result: function() {
		this.is_started = false;
		this.view.hide();
		this.view = this.result_view;
		this.view.show();
	},
	
	active: function() {
		this.init();
	},
	
	close: function($super) {
		if (this.is_started && !confirm('퀴즈 진행 중입니다. 퀴즈를 종료하시겠습니까?'))
			return false;
		
		return $super();
	},
	
	onKeyDown: function(event) {
		if (!this.is_started)
			return;
		
		var key = event.which || event.keyCode;
		
		switch (key)
		{
		case 32:
			this.check();
			break;
		case 49: case 97: // '1', NUM1
			this.check(0);
			break;
		case 50: case 98: // '2', NUM2
			this.check(1);
			break;
		case 51: case 99: // '3', NUM3
			this.check(2);
			break;
		case 52: case 100: // '4', NUM4
			this.check(3);
			break;
		case Event.KEY_UP: 
			if (event.ctrlKey)
				this.view.increaseFontSize();
			break;
		case Event.KEY_DOWN:
			if (event.ctrlKey)
				this.view.decreaseFontSize();
			break;
		}
	}
});

var ConfigController = Class.create(Controller, {
	initialize: function(app) {
		this.app = app;
		this.view = new ConfigView(this);
	},
	
	onLoad: function() {
		if (!this.app.data.book_id)
			return;
		
		this.app.config_data.load();
	},
	
	apply: function() {
		if (!this.app.config_data.is_loaded)
			return;
		
		this.app.config_data.delay_time = parseInt($F('InputDelayTime'));
		this.app.config_data.always_on_top = $('InputAlwaysOnTop').checked;
		this.app.config_data.auto_play = $('InputAutoStart').checked;
		this.app.config_data.sound_auto_play = $('InputSoundAutoPlay').checked;
		
		this.app.config_data.save();
		
		alert('적용 되었습니다.');
	},
	
	alwaysOnTop: function() {
		if (!Prototype.Browser.IE)
		{
			alert('해당 기능은 ActiveX의 설치가 필요하며, Internet Explorer에서만 사용 가능합니다.');
			$('InputAlwaysOnTop').checked = false;
			return;
		}
		
		if (WordbreakHelper.object == null)
		{
			var options = 'width=' + 300 + ', height=' + 300 + 
				', left=' + (screen.availWidth - 300) / 2 + ', top=' + (screen.availHeight - 300) / 2 + 
				', toolbar=no, location=no, directories=no, status=no, menubar=no, resizable=yes, scrollbars=no';
			window.open(ROOT_URL + 'player/helper', '', options);
			$('InputAlwaysOnTop').checked = false;
			return;
		}
		
		WordbreakHelper.AlwaysOnTop = $('InputAlwaysOnTop').checked;
	},
	
	close: function($super) {
		if (WordbreakHelper.object != null)
			WordbreakHelper.AlwaysOnTop = this.app.config_data.always_on_top;
		
		return $super();
	}
});

var Data = Class.create({
	initialize: function(app, data_url) {
		this.app = app;
		this.data_url = data_url;
		
		this.vocabs = [];
		this.index = this.default_index = this.order_index = this.random_index = null;
		this.type = 'default';
		
		this.is_loaded = false;
	},
	
	load: function() {
		var model = this;
		new Ajax.Request(this.data_url, {
			onSuccess: function(reponse) {
				try {
					model._loadData(reponse.responseText.evalJSON());
					model.app.onLoad();
				} catch(e) {
					model.app.onLoadFailed();
				}
			},
			onFailure: function() {
				model.app.onLoadFailed();
			}
		});
	},
	
	isLoaded: function() {
		return this.is_loaded;
	},
	
	_loadData: function(data) {
		this.book_id = data.book_id;
		this.title = data.title;
		this.access_status = data.access_status;
		
		this.app.player.sound.load(data.sound_plugin);
		this.app.player.image.load(data.image_plugin);
		this.app.player.style.load(data.style_plugin);
		
		this.vocabs = data.vocabs;
		this.vocabs.pop();
		
		if (this.vocabs.length > 0)
			this.index = this.default_index = $A($R(0, this.vocabs.length - 1));
		
		this.is_loaded = true;
	},
	
	count: function() {
		return this.index.length;
	},
	
	getOrderIndex: function() {
		if (!this.order_index)
		{
			var vocabs = this.vocabs;
			this.order_index = this.default_index.reject(function(idx) {
				return vocabs[idx][4];
			});
			
			this.order_index = this.order_index.sort(function(a, b) {
				return vocabs[a][0] > vocabs[b][0] ? 1 : (vocabs[a][0] < vocabs[b][0] ? -1 : 0);
			});
		}
			
		return this.order_index;
	},
	
	getRandomIndex: function() {
		if (!this.random_index)
			this.random_index = this.getOrderIndex().clone();
		
		return this.random_index.sort(function(a, b) {
			return Math.round(Math.random()) - 0.5;
		});
	},
	
	order: function(type) {
		switch (type)
		{
			case 'default': default:
				this.index = this.default_index;
				break;
			case 'order':
				this.index = this.getOrderIndex();
				break;
			case 'random':
				this.index = this.getRandomIndex();
				break;
		}
		this.type = type;
	},
	
	getVocab: function(idx) {
		return this.vocabs[this.index[idx]];
	},
	
	deleteIndex: function(idx) {
		var viid = this.vocabs[idx][3];
		
		this.default_index = this.default_index.without(idx);
		if (this.order_index)
			this.order_index = this.order_index.without(idx);
		if (this.random_index)
			this.random_index = this.random_index.without(idx);
		
		this.index = $H({'default': this.default_index, 'order': this.order_index, 'random': this.random_index}).get(this.type);
		
		return viid;
	}
});

var ConfigData = Class.create({
	initialize: function(app) {
		this.app = app;
		
		this.is_loaded = false;
		this.default_data = {'quiz_count': 10, 'delay_time': 5, 'always_on_top': false, 'sound_auto_play': true, 'auto_play': true};
		
		this.quiz_count = this.default_data.quiz_count;
		this.delay_time = this.default_data.delay_time;
		this.always_on_top = this.default_data.always_on_top;
		this.sound_auto_play = this.default_data.sound_auto_play;
		this.auto_play = this.default_data.auto_play;
	},
	
	load: function() {
		var quiz_count = Cookie.read('PlayerConfig.quiz_count');
		var delay_time = Cookie.read('PlayerConfig.delay_time');
		var always_on_top = Cookie.read('PlayerConfig.always_on_top');
		var sound_auto_play = Cookie.read('PlayerConfig.sound_auto_play');
		var auto_play = Cookie.read('PlayerConfig.auto_play');
		
		if (quiz_count)
			this.quiz_count = parseInt(quiz_count);
		if (delay_time)
			this.delay_time = parseInt(delay_time);
		if (always_on_top != null)
			this.always_on_top = parseInt(always_on_top);
		if (sound_auto_play != null)
			this.sound_auto_play = parseInt(sound_auto_play);
		if (auto_play != null)
			this.auto_play = parseInt(auto_play);
		
		this.is_loaded = true;
	},
	
	save: function() {
		Cookie.write('PlayerConfig.quiz_count', this.quiz_count);
		Cookie.write('PlayerConfig.delay_time', this.delay_time);
		Cookie.write('PlayerConfig.always_on_top', this.always_on_top ? 1 : 0);
		Cookie.write('PlayerConfig.sound_auto_play', this.sound_auto_play ? 1 : 0);
		Cookie.write('PlayerConfig.auto_play', this.auto_play ? 1 : 0);
	}
});

var View = Class.create({
	initialize: function(controller) {
		this.controller = controller;
		this.view_element = null;
		this.background_element = null;
		this.bottom_element = null;
		
		this.top_menu_status = [false, false, false, false];
	},
	
	update: function() {
		this._repositionViewElement();
	},
	
	onResize: function() {
		this._resizeBackgroundElement();
		this._repositionViewElement();
	},
	
	_resizeBackgroundElement: function() {
		if (!this.background_element)
			return;
		
		this.background_element.style.height = $('ViewFrame').style.height;
	},
	
	_repositionViewElement: function() {
		if (!this.view_element)
			return;
		
		Wordbreak.repositionViewElement(this.view_element);
	},
	
	show: function() {
		if (!this.view_element)
			return;
		
		$('PlaySound')[this.top_menu_status[0] ? 'addClassName' : 'removeClassName']('Enable');
		$('IncreaseFontSize')[this.top_menu_status[1] ? 'addClassName' : 'removeClassName']('Enable');
		$('DecreaseFontSize')[this.top_menu_status[2] ? 'addClassName' : 'removeClassName']('Enable');
		$('ToggleMiniMode')[this.top_menu_status[3] ? 'addClassName' : 'removeClassName']('Enable');
		
		if (this.background_element)
		{
			this._resizeBackgroundElement();
			this.background_element.show();
		}
		
		if (this.bottom_element)
			this.bottom_element.show();
		
		this.view_element.show();
		this.update();
	},
	
	hide: function() {
		if (!this.view_element)
			return;
		
		if (this.bottom_element)
			this.bottom_element.hide();
		
		if (this.background_element)
			this.background_element.hide();
		
		this.view_element.hide();
	}
});

var LoadingView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('LoadingView');
		this.bottom_element = $('PlayerBottom');
	},
	
	update: function($super) {
		if (this.controller.load_status < 0)
		{
			$('LoadingViewText1').hide();
			$('LoadingViewText2').show();
		}
		$super();
	}
});

var PlayerView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('PlayerView');
		this.background_element = $('PlayerBackground');
		this.bottom_element = $('PlayerBottom');
		
		this.top_menu_status = [controller.sound.isEnable(), true, true, true];
		
		this._updateStyle();
		
		this.font_size = 1;
		this._updateFontSize();
		
		if (controller.style.data.background)
			$('ViewFrame').removeClassName('Default');
	},
	
	_updateStyle: function() {
		var style = this.controller.style.data;
		
		if (style.background)
			this.background_element.style.background = style.background;
		
		$('PlayerViewName').setStyle({
			'background': style['name']['background'] ? style['name']['background'] : '', 
			'fontFamily': style['name']['font'] ? style['name']['font'] : '',
			'color': style['name']['color'],
			'fontStyle': style['name']['italic'] ? 'italic' : '', 
			'fontWeight': style['name']['bold'] ? 'bold' : ''
		});
		$('PlayerViewMean').setStyle({
			'background': style['mean']['background'] ? style['mean']['background'] : '', 
			'fontFamily': style['mean']['font'] ? style['mean']['font'] : '',
			'color': style['mean']['color'],
			'fontStyle': style['mean']['italic'] ? 'italic' : '', 
			'fontWeight': style['mean']['bold'] ? 'bold' : ''
		});
		$('PlayerViewExample').setStyle({
			'background': style['example']['background'] ? style['example']['background'] : '', 
			'fontFamily': style['example']['font'] ? style['example']['font'] : '',
			'color': style['example']['color'],
			'fontStyle': style['example']['italic'] ? 'italic' : '', 
			'fontWeight': style['example']['bold'] ? 'bold' : ''
		});
	},
	
	toggleName: function() {
		$('PlayerViewName')[$('ToggleName').toggleClassName('On').hasClassName('On') ? 'show': 'hide']();
		this._repositionViewElement();
	},
	
	toggleMean: function() {
		$('PlayerViewMean')[$('ToggleMean').toggleClassName('On').hasClassName('On') ? 'show': 'hide']();
		this._repositionViewElement();
	},
	
	toggleExample: function() {
		$('PlayerViewExample')[$('ToggleExample').toggleClassName('On').hasClassName('On') ? 'show': 'hide']();
		this._repositionViewElement();
	},
	
	toggleMeanExample: function() {
		var visible = $('ToggleMean').toggleClassName('On').hasClassName('On');
		if ($('ToggleExample').hasClassName('On') != visible)
			$('ToggleExample').toggleClassName('On');
		$('PlayerViewMean', 'PlayerViewExample').invoke(visible ? 'show': 'hide');
		this._repositionViewElement();
	},
	
	toggleMiniMode: function() {
		$('Top', 'Bottom').invoke('toggle');
		$('ToggleMiniModeFloat')[$('Top').visible() ? 'hide' : 'show']();
		Wordbreak.resizeViewFrame();
		this.onResize();
	},
	
	increaseFontSize: function() {
		this.font_size *= 1.2;
		this._updateFontSize();
		this._repositionViewElement();
	},
	
	decreaseFontSize: function() {
		this.font_size /= 1.2;
		this._updateFontSize();
		this._repositionViewElement();
	},
	
	_updateFontSize: function() {
		var size = {
			'name': this.font_size * this.controller.style.data['name']['size'],
			'mean': this.font_size * this.controller.style.data['mean']['size'],
			'example': this.font_size * this.controller.style.data['example']['size']
		};
		$('PlayerViewName').setStyle({'fontSize': size['name'] + 'pt', 'lineHeight': (size['name'] * 1.5) + 'pt' });
		$('PlayerViewMean').setStyle({'fontSize': size['mean'] + 'pt', 'lineHeight': (size['mean'] * 1.5) + 'pt' });
		$('PlayerViewExample').setStyle({'fontSize': size['example'] + 'pt', 'lineHeight': (size['example'] * 1.5) + 'pt' });
	},
	
	order: function(type) {
		$('ToggleMode').removeClassName('ToggleModeDefault');
		$('ToggleMode').removeClassName('ToggleModeOrder');
		$('ToggleMode').removeClassName('ToggleModeRandom');
		$('ToggleMode').addClassName('ToggleMode' + type.capitalize());
	},
	
	update: function($super) {
		var vocab = this.controller.app.data.getVocab(this.controller.position);
		$('PlayerViewName').update(vocab[0]);
		$('PlayerViewMean').update(vocab[1]);
		$('PlayerViewExample').update(vocab[2]);
		
		this._updatePosition();
		$('PlayerViewImage').hide();
		this.controller.image.show();
		
		$super();
	},
	
	updatePlayButton: function() {
		$('Play')[this.controller.is_playing ? 'addClassName' : 'removeClassName']('Pause');
	},
	
	updateCountdown: function() {
		if (this.controller.countdown_number < 1)
		{
			$('Countdown').hide();
		}
		else if (this.controller.countdown_number < 4)
		{
			$('Countdown').show();
			$('Countdown').update(this.controller.countdown_number);
		}
	},
	
	_updatePosition: function() {
		var position = this.controller.position + 1;
		var item_count = this.controller.app.data.count();
		$('PlayerPosition').update(position);
		$('PlayerItemCount').update(item_count);
		$('PlayerProgressBar').style.width = (position / item_count * 100) + '%';
	}
});

var QuizStartView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('QuizStartView');
	},
	
	show: function($super) {
		if (this.controller.quiz_type == 'name-mean')
			$('QuizTypeNameMean').checked = true;
		
		$('InputQuizCount').value = this.controller.app.config_data.quiz_count;
		
		$super();
	}
});

var QuizLoadingView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('QuizLoadingView');
	}
});

var QuizView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('QuizView');
		this.background_element = $('QuizBackground');
		this.bottom_element = $('QuizBottom');
		
		this.font_size = 1;
		this._updateFontSize();
		
		this.top_menu_status = [false, true, true, false];
	},
	
	update: function($super) {
		switch (this.controller.question_status)
		{
		case 'active':
			$('Answer0', 'Answer1', 'Answer2', 'Answer3').invoke('removeClassName', 'Wrong');
			$('Answer0', 'Answer1', 'Answer2', 'Answer3').invoke('removeClassName', 'Correct');
			$('QuizBackground').removeClassName('CorrectQuizBackground').removeClassName('WrongQuizBackground');
			
			var quiz_type_info = $H({'name-mean': [0, 1], 'mean-name': [1, 0]}).get(this.controller.quiz_type);
			
			var question_idx = this.controller.question_index[this.controller.position];
			$('Question').update(this.controller.app.data.vocabs[question_idx][quiz_type_info[0]]);
			
			var answer_index = this.controller.answer_indexes[this.controller.position];
			for (var i = 0; i < answer_index.length; ++i)
			{
				$('AnswerData' + i).update(this.controller.app.data.vocabs[answer_index[i]][quiz_type_info[1]]);
			}
			
			this._updatePosition();
			break;
			
		case 'answered':
			if (this.controller.wrong_answer != null && this.controller.wrong_answer != this.controller.correct_answer)
				$('Answer' + this.controller.wrong_answer).addClassName('Wrong');
			$('Answer' + this.controller.correct_answer).addClassName('Correct');
			$('QuizBackground').addClassName(this.controller.wrong_answer == null && this.controller.wrong_answer != this.controller.correct_answer ? 'CorrectQuizBackground' : 'WrongQuizBackground');
			break;
		}
		
		this._updateBottom();
		
		$super();
	},
	
	_updateBottom: function() {
		$('BtnCheckQuestion', 'BtnNextQuestion', 'BtnQuizResult').invoke('hide');
		
		switch (this.controller.question_status)
		{
		case 'active':
			$('BtnCheckQuestion').show();
			break;
			
		case 'answered':
			$((this.controller.position < this.controller.quiz_count - 1) ? 'BtnNextQuestion' : 'BtnQuizResult').show();
			break;
		}
	},
	
	_updatePosition: function() {
		var position = this.controller.position + 1;
		var item_count = this.controller.quiz_count;
		$('QuizPosition').update(position);
		$('QuizItemCount').update(item_count);
		$('QuizProgressBar').style.width = (position / item_count * 100) + '%';
	},
	
	increaseFontSize: function() {
		this.font_size *= 1.2;
		this._updateFontSize();
		this._repositionViewElement();
	},
	
	decreaseFontSize: function() {
		this.font_size /= 1.2;
		this._updateFontSize();
		this._repositionViewElement();
	},
	
	_updateFontSize: function() {
		var size = {
			'question': this.font_size * 20,
			'answer': this.font_size * 10
		};
		$('Question').setStyle({'fontSize': size['question'] + 'pt', 'lineHeight': (size['question'] * 1.5) + 'pt'});
		$$('a.Answer').invoke('setStyle', {'fontSize': size['answer'] + 'pt', 'lineHeight': (size['answer'] * 1.4) + 'pt'});
	}
});

var QuizResultView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('QuizResultView');
	},
	
	update: function($super) {
		$('QuizScore').update(this.controller.score);
		$('QuizCount').update(this.controller.quiz_count);
		
		$super();
	}
});

var ConfigView = Class.create(View, {
	initialize: function($super, controller) {
		$super(controller);
		this.view_element = $('ConfigView');
	},
	
	update: function($super) {
		$('InputDelayTime', 'InputAlwaysOnTop', 'InputAutoStart', 'InputSoundAutoPlay').invoke(this.controller.app.config_data.is_loaded ? 'enable' : 'disable');
		
		$('InputDelayTime').value = this.controller.app.config_data.delay_time;
		$('InputAlwaysOnTop').checked = this.controller.app.config_data.always_on_top;
		$('InputAutoStart').checked = this.controller.app.config_data.auto_play;
		$('InputSoundAutoPlay').checked = this.controller.app.config_data.sound_auto_play;
		
		$super();
	}
});

var Plugin = Class.create({
	initialize: function(player) {
		this.player = player;
		this.data = null;
	},
	
	isEnable: function() {
		return (this.data != null);
	},
	
	load: function(data) {
		if (data != null)
			this.data = data;
	},
	
	_parseUrl: function(index, callback)
	{
		var vocabs = this.player.app.data.vocabs;
		var url = this.data.url;
		url = url.gsub(/%id%/, index + 1);
		url = url.gsub(/%name%/, encodeURIComponent(vocabs[index][0].strip())); // name
		url = url.gsub(/%name_l%/, encodeURIComponent(vocabs[index][0].toLowerCase().strip())); // name_l
		url = url.gsub(/%mean%/, encodeURIComponent(vocabs[index][1].strip())); // mean
		url = url.gsub(/%example%/, encodeURIComponent(vocabs[index][2].strip())); // example
		
		switch (this.data.url_type)
		{
		case 'url':
			new Ajax.Request('/player/read_url', {
				parameters: { 'url': url },
				onSuccess: function(response) {
					callback(response.responseText);
				}
			});
			break;
		default:
			callback(url);
			break;
		}
	}
});

var SoundPlugin = Class.create(Plugin, {
	initialize: function($super, player) {
		$super(player);
		this.url_cache = $A();
	},
	
	play: function() {
		if (!this.isEnable())
			return;
		
		var idx = this.player.app.data.index[this.player.position];
		if (this.url_cache[idx] != undefined)
		{
			Wordbreak.playSound(this.url_cache[idx][1], this.url_cache[idx][0]);
			return;
		}
		
		var plugin = this;
		this._parseUrl(idx, function(url) {
			plugin.url_cache[idx] = [url, plugin.data.file_type];
			Wordbreak.playSound(plugin.data.file_type, url);
		});
	}
});

var ImagePlugin = Class.create(Plugin, {
	initialize: function($super, player) {
		$super(player);
		this.url_cache = $A();
	},
	
	show: function() {
		if (!this.isEnable())
			return;
		
		var idx = this.player.app.data.index[this.player.position];
		var view_element = this.player.view.view_element;
		if (this.url_cache[idx] != undefined)
		{
			Wordbreak.showImage(this.url_cache[idx]);
			return;
		}
		
		var plugin = this;
		this._parseUrl(idx, function(url) {
			plugin.url_cache[idx] = url;
			Wordbreak.showImage(url);
		});
	}
});

var StylePlugin = Class.create(Plugin, {
	initialize: function($super, player) {
		$super(player);
		this.data = this.default_data = {
			'background': null,
			'name': {'background': null, 'font': null, 'color': '#000', 'size': 14, 'bold': false, 'italic': false},
			'mean': {'background': null, 'font': null, 'color': '#000', 'size': 10, 'bold': false, 'italic': false},
			'example': {'background': null, 'font': null, 'color': '#000', 'size': 9, 'bold': false, 'italic': false}
		};
	},
	
	load: function(data) {
		if (data != null)
			this.data = data;
		
		if (this.data.name.size == null)
			this.data.name.size = this.default_data.name.size;
		if (this.data.mean.size == null)
			this.data.mean.size = this.default_data.mean.size;
		if (this.data.example.size == null)
			this.data.example.size = this.default_data.example.size;
	}
});

var Cookie = {
	write: function(name, value, days) {
		var expires = '';
		if (days)
		{
			var date = new Date();
			date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
			expires = ';expires=' + date.toGMTString();
		}
		document.cookie = name + '=' + value + expires + ';path=/';
	},
	
	read: function(name) {
		var name_eq = name + '=';
		var cookies = document.cookie.split(';');
		for (var i = 0; i < cookies.size(); ++i)
		{
			var cookie = cookies[i].strip();
			if (cookie.startsWith(name_eq))
				return cookie.substring(name_eq.length, cookie.length);
		}
		return null;
	},
	
	del: function(name) {
		Cookie.write(name, '', -1);
	}
};

Event.observe(window, 'load', function() {
	app = new App(DATA_URL);
});
