/**********************************************************************
* Copyright (C) 2007 Kyoto University
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
* 
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
* 
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-
* 1301  USA
***********************************************************************/
/*
 * A class to make a translation path by selecting languages and translator(s) is defined in this file.
 */

var TranslatorsAndLanguagesSelection = Class.create();

TranslatorsAndLanguagesSelection.prototype = {
	languageMenuElements: [],
	translatorMenuElements: [],
	checkBoxElement: null,
	translatorsProperty: null,
	domReady: false,
	messageManager: null, //* MessageManager
	controller: null, 
	backTranslationManager: null, //* BackTranslationManager
	
	permittedThirdLanguageButtonAction: null, //* Enable Second Translationが許可されている時のボタンのイベント
	prohibittedThirdLanguageButtonAction: null, //* Enable Second Translationが禁止されている時のボタンのイベント
	isPermitted: true, //* 3言語モード許可かそうでないかの変数
	
	initialize: function(controller, messageManager, backTranslationManager){
		this.controller = controller;
		this.messageManager = messageManager;
		this.backTranslationManager = backTranslationManager;
	},
	
	setProperties: function(obj){
		this.languageMenuElements.push($(obj.lang1Id));
		this.languageMenuElements.push($(obj.lang2Id));
		this.languageMenuElements.push($(obj.lang3Id));
		
		this.translatorMenuElements.push($(obj.translator1Id));
		this.translatorMenuElements.push($(obj.translator2Id));
		
		this.checkBoxElement = $(obj.checkBoxId);
		this.checkBoxElement.checked = false;
		
		this._initAction(obj.initialSourceLanguage, obj.initialTargetLanguage);
		this._setEvent();
	},
	
	_initAction: function(initSource, initTarget){
		var selector = this;
		new Ajax.Request(
			 './php/ajax/load-services.php',
			 {
				 method		:'post',
				 parameters	:'serviceCategory=translation',
				 selector	:selector,
				 onSuccess	:function(httpObj){
					var responseObject = eval("("+httpObj.responseText+")");
					var checker = new StatusProcessor(responseObject,
						"Playground Error : Can't obtain information about translators.",
						"Playground Warning : Can't obtain information about all translators.");
					if (!checker.check()) {
						return;
					}
					selector.translatorsProperty = responseObject.contents;
					
					//* 対訳関係のペア作成処理
					for(var i=0;i<selector.translatorsProperty.size();i+=1){
						for(var j=0;j<selector.translatorsProperty[i]['path'].size();j++){
							var pair = selector.translatorsProperty[i]['path'][j].split('2');
							selector.translatorsProperty[i]['path'][j] = new Pair(pair[0],pair[1]);
						}
					}
					
					selector._setInitialView(initSource, initTarget);
				 },
				 onFailure	:function(){
					 alert('Server Connection Error');
				 }
			 }
		)
	},
	
	_setInitialView: function(initSource, initTarget){
		var selector = this;
		this.translatorMenuElements.each(function(e){
			selector.translatorsProperty.each(function(t){
				var elem = document.createElement("option");
				elem.appendChild(document.createTextNode(t.name));
				elem.value = t.id;
				e.appendChild(elem);
			});
		});
		
		this.setLanguagesToMenu(0, this._getSupportedSourceLanguages(
			this.translatorMenuElements[0].value), initSource);
			
		this.setLanguagesToMenu(1, this._getSupportedTargetLanguages(
			this.translatorMenuElements[0].value, this.languageMenuElements[0].value), initTarget);
			
		this.setLanguagesToMenu(2, this._getSupportedTargetLanguages(
			this.translatorMenuElements[1].value, this.languageMenuElements[1].value));
			
		this.translatorMenuElements[1].disable();
		this.languageMenuElements[2].disable();
		
		this.domReady = true;
	},
	
	_getSupportedSourceLanguages: function(translatorId){
		var languages = [];
		this._getTranslatorProperty(translatorId)['path'].each(function(p){
			if (languages.indexOf(p.car()) == -1) {
				languages.push(p.car());
			}
		});
		return languages;
	},
	
	_getSupportedTargetLanguages: function(translatorId, sourceLanguage){
		var languages = [];
		this._getTranslatorProperty(translatorId)['path'].each(function(p){
			if (sourceLanguage != null) {
				if (sourceLanguage == p.car() && languages.indexOf(p.cdr()) == -1) {
					languages.push(p.cdr());
				}
			}
			else if (languages.indexOf(p.cdr()) == -1) {
				languages.push(p.cdr());
			}
		});
		return languages;
	},
	
	_getTranslatorProperty: function(translatorId){
		for (var i = 0; i < this.translatorsProperty.size(); i++) {
			if (this.translatorsProperty[i].id == translatorId) {
				return this.translatorsProperty[i];
			}
		}
		return null;
	},
	
	//* それぞれの要素のリスナを追加する
	_setEvent: function(){
		var selector = this;
		this.languageMenuElements.each(function(e, index){
			e.observe('change', selector._onChangeLanguageMenu.bindAsEventListener(selector, index));
		});
		this.translatorMenuElements.each(function(e, index){
			e.observe('change', selector._onChangeTranslatorMenu.bindAsEventListener(selector, index));
		});
		this.permittedThirdLanguageButtonAction = this._onChangeCheckBox.bindAsEventListener(this);
		this.prohibittedThirdLanguageButtonAction = this._onChangeCheckBoxInProhibition.bindAsEventListener(this);
		this.checkBoxElement.observe('click', this.permittedThirdLanguageButtonAction);
	},
	
	//* 翻訳機が変わったときのアクション
	_onChangeTranslatorMenu: function(ev){
		var index = $A(arguments)[1];
		if(index == 0) {
			var sourceLanguages = this._getSupportedSourceLanguages(this.translatorMenuElements[index].value)
			if (sourceLanguages.indexOf(this.languageMenuElements[index].value) == -1) {
				this.setLanguagesToMenu(index, sourceLanguages);
				var editors = this.controller.getEditors();
				var editorIndex = this.controller.getEditorIndex();
				for (var i = 0; i < editors.size(); i++) {
					editors[i].setButtonLabel(editorIndex[index], Language.getNameByTag(this.languageMenuElements[index].value));
					editors[i].setDirection();
				}
			}
			else {
				this.setLanguagesToMenu(index, sourceLanguages, this.languageMenuElements[index].value);
			}
		}
		this.__changeLanguageModule(index);
		//* 折り返し翻訳エリアの言語パスの表示の変更
		this.backTranslationManager.setBacktranslationPath();
		this.messageManager.setSourceLanguage(); //* メッセージ管理者の翻訳元言語更新
	},
	
	//* 言語が変わったときのアクション
	_onChangeLanguageMenu: function(ev){
		langTagArray = new Array();
		IsATagAlreadyAdded = new Array();
		for(i=0; i<this.languageMenuElements.length; i++){
			if (IsATagAlreadyAdded[this.languageMenuElements[i].value] !== true) {
				langTagArray.push(this.languageMenuElements[i].value)
			}
				
			IsATagAlreadyAdded[this.languageMenuElements[i].value] = true;
		}
		
		//* 対訳のfromを書き換える
		this.controller.parallelTextSearchObj.changeSourceLanguages(langTagArray);
		
		var index = $A(arguments)[1];
		var editors = this.controller.getEditors();
		var editorIndex = this.controller.getEditorIndex();
		for(var i=0;i<editors.size();i++){
			editors[i].setButtonLabel(editorIndex[index], Language.getNameByTag(this.languageMenuElements[index].value));
			editors[i].setDirection();
		}
		this.__changeLanguageModule(index);
		//* 折り返し翻訳エリアの言語パスの表示の変更
		this.backTranslationManager.setBacktranslationPath();
		this.messageManager.setSourceLanguage(); //* メッセージ管理者の翻訳元言語更新
	},
	
	//* Enable Second Translation ボタンが変わったときのアクション
	_onChangeCheckBox: function(ev){
		if(this.checkBoxElement.checked){
			this.languageMenuElements[2].enable();
			this.translatorMenuElements[1].enable();
			this.controller.enableThirdLanguage();
		} else {
			this.languageMenuElements[2].disable();
			this.translatorMenuElements[1].disable();
			this.controller.disableThirdLanguage();
		}
		//* 折り返し翻訳エリアの言語パスの表示の変更
		this.backTranslationManager.setBacktranslationPath();
		this.messageManager.setSourceLanguage(); //* メッセージ管理者の翻訳元言語更新
	},
	
	//* Enable Second Translation ボタンがクリック禁止モードで変わったときのアクション
	_onChangeCheckBoxInProhibition: function(ev){
		alert('We do not have any translator which supports "'
			+Language.getNameByTag(this.languageMenuElements[1].value)
			+'" as a source language.');
		if (this.checkBoxElement.checked) {
			this.uncheckThirdLanguageCheckbox();
		}
	},
	
	//* 選択言語を変えるメソッド．_onChangeTranslatorMenu と _onChangeLanguageMenuから呼ばれる
	//* index{Integer} 言語選択メニューのインデックス
	//* firstTranslator{String} ループ検出のために，ループの最初の翻訳機名を記憶しておく
	__changeLanguageModule: function(index, firstTranslator){
		if (index == 2) {
			this._permitThirdLanguage();
			return;
		}
		var editors = this.controller.getEditors();
		var editorIndex = this.controller.getEditorIndex();
		var targetLanguages = this._getSupportedTargetLanguages(
			this.translatorMenuElements[index].value, this.languageMenuElements[index].value);
		if(targetLanguages.size() == 0) { 
			//* 3つ目の言語を設定する場合に，対象言語が設定されない場合がある．その場合は翻訳機を変えてみる
			//* Parsitなどを利用した場合には無限ループに陥る可能性がある．それを防ぐためにループを検出する
			if(!firstTranslator) firstTranslator = this.translatorMenuElements[index].value;
			this._nextTranslator(index);
			if (firstTranslator == this.translatorMenuElements[index].value) { //* ループ検出
				this._prohibitThirdLanguage();
			}
			else {
				this.__changeLanguageModule(index, firstTranslator);
			}
		}else if(targetLanguages.indexOf(this.languageMenuElements[index+1].value) != -1){
			this.setLanguagesToMenu(index+1, targetLanguages, this.languageMenuElements[index+1].value);
			this._permitThirdLanguage();
		} else {
			this.setLanguagesToMenu(index+1, targetLanguages);
			for(var i=0;i<editors.size();i++){
				editors[i].setButtonLabel(editorIndex[index+1], Language.getNameByTag(this.languageMenuElements[index+1].value));
				editors[i].setDirection();
			}
			index++;
			this.__changeLanguageModule(index);
		}
	},
	
	//* 翻訳機をセレクトメニューの次の翻訳機に変える
	_nextTranslator: function(index){
		var nowTranslator = this.translatorMenuElements[index].value;
		var translators = [];
		Element.childElements(this.translatorMenuElements[index]).each(function(opt){
			translators.push(opt.value);
		});
		this.translatorMenuElements[index].value = translators[(translators.indexOf(nowTranslator) + 1) % translators.size()];
	},
	
	//* Persitなどを用いたときにはthから目標言語を指定することはできない
	//* 3言語目の言語，翻訳機を空にして，"enable second translation"ボタンをクリック不可にする
	//* もし，3言語モードだった場合，強制的に2言語にする
	_prohibitThirdLanguage: function(){
		if(this.isEnableThirdLanguage()){
			if(BrowserIdentifier.isIE()){
				this.uncheckThirdLanguageCheckbox();
			}
			EventDispatcher.prototype.click($("check_box"));
		}
		this.translatorMenuElements[1].value = '';
		this.languageMenuElements[2].value = '';
		if(this.isPermitted){
			this.isPermitted = false;
			this.checkBoxElement.stopObserving('click', this.permittedThirdLanguageButtonAction);
			this.checkBoxElement.observe('click',this.prohibittedThirdLanguageButtonAction);
		}
	},
	
	//* 多くの場合，3言語目は指定可となるように命令される
	_permitThirdLanguage: function(){
		if(!this.isPermitted) {
			this.isPermitted = true;
			this.checkBoxElement.stopObserving('click',this.prohibittedThirdLanguageButtonAction);
			this.checkBoxElement.observe('click',this.permittedThirdLanguageButtonAction);
		}
	},
	
	checkThirdLanguageCheckbox: function(){
		this.checkBoxElement.checked = true;
	},
	
	uncheckThirdLanguageCheckbox: function(){
		this.checkBoxElement.checked = false;
	},
	
	isEnableThirdLanguage: function(){
		return this.checkBoxElement.checked;
	},
	
	setLanguagesToMenu: function(index, languages, init){
		var selector = this;
		selector.languageMenuElements[index].innerHTML = '';
		languages.each(function(l){
			var elem = document.createElement("option");
			elem.appendChild(document.createTextNode(Language.getNameByTag(l)));
			elem.value = l;
			if (init && init == l) {
				elem.selected = true;
			}
			selector.languageMenuElements[index].appendChild(elem);
		})
		//*if(init) selector.languageMenuElements[index].value = init;
		
		//* 用例対訳コンポーネントの言語選択状況を書き換える
		//* TODO　各コンポーネント同士の関連がコンポーネントに書かれるのは不格好なので、
		//* ドキュメント翻訳のmainスクリプトにこの処理を移動
		
		langTagArray = new Array();
		isAlreadyAdded = new Array();
		for(i=0; i<this.languageMenuElements.length; i++){
			if (isAlreadyAdded[this.languageMenuElements[i].value] !== true) {
				langTagArray.push(this.languageMenuElements[i].value);
			}
				
			isAlreadyAdded[this.languageMenuElements[i].value] = true;
		}
		
		//* 対訳のfromとtoを書き換える
		this.controller.parallelTextSearchObj.changeSourceLanguages(langTagArray);
	},
	
	getLanguages: function(){
		var languages = [this.languageMenuElements[0].value, this.languageMenuElements[1].value];
		if(this.controller.isEnableThirdLanguage() && 
			!(this.languageMenuElements[2].value == null || this.languageMenuElements[2].value == '')){
			languages.push(this.languageMenuElements[2].value);
		}
		return languages;
	},
	
	getTranslatorIds: function(){
		var translatorIds = [this.translatorMenuElements[0].value];
		if(this.controller.isEnableThirdLanguage() && 
			!(this.languageMenuElements[2].value == null || this.languageMenuElements[2].value == '')){
			translatorIds.push(this.translatorMenuElements[1].value);
		}
		return translatorIds;
	}
}
