/**********************************************************************
 * /js/util/utilities.js
 * Copyright (C) 2007-2008 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
 ***********************************************************************/
var Pair = Class.create();
var StatusProcessor = Class.create();
var EventDispatcher = Class.create();
var BrowserIdentifier = Class.create();

Pair.prototype = {
    initialize: function(first, second){
        this.first = first;
        this.second = second;
    },
    
    //* 一つ目の要素の代入
    setFirst: function(obj){
        this.first = obj;
    },
    
    //* 一つ目の要素の取得
    getFirst: function(){
        return this.first;
    },
    
    //* 二つ目の要素の代入
    setSecond: function(obj){
        this.second = obj;
    },
    
    //* 二つ目の要素の取得
    getSecond: function(){
        return this.second;
    },
    
    //* Lisp風メソッド
    //* @alias	getFirst
    car: function(){
        return this.getFirst();
    },
    
    //* Lisp風メソッド
    //* @alias	getFirst
    cdr: function(){
        return this.getSecond();
    },
    
    //* Lisp風メソッド
    caar: function(){
        return this.car().car();
    },
    cdar: function(){
        return this.cdr().car();
    },
    cadr: function(){
        return this.car().cdr();
    },
    cddr: function(){
        return this.cdr().cdr();
    },
    
    caaar: function(){
        return this.car().car().car();
    },
    cadar: function(){
        return this.car().cdr().car();
    },
    caadr: function(){
        return this.car().car().cdr();
    },
    caddr: function(){
        return this.car().cdr().cdr();
    },
    cdaar: function(){
        return this.cdr().car().car();
    },
    cddar: function(){
        return this.cdr().cdr().car();
    },
    cdadr: function(){
        return this.cdr().car().cdr();
    },
    cdddr: function(){
        return this.cdr().cdr().cdr();
    }
};

//* レスポンスのオブジェクトのステータスを処理するオブジェクト
//* alert部分の拡張は可能かもしれない
StatusProcessor.prototype = {
    LIMITATION_ERROR_MESSAGE: "Service Limitation Error",
    LIMITATION_WARNING_MESSAGE: "Service Limitation Warning",
    
    initialize: function(responseObj, errorMessage, warningMessage){
        this.response = responseObj;
        this.status = this.response.status;
        this.message = this.response.message;
        this.contents = this.response.contents;
        this.warningMessage = warningMessage;
        this.errorMessage = errorMessage;
    },
    
    check: function(){
        if (this.status == 'ERROR') {
            return this.error();
        }
        else 
            if (this.status == 'WARNING') {
                return this.warning();
            }
            else 
                if (this.status == 'OK') {
                    return this.ok();
                }
                else {
                    return this.other();
                }
    },
    
    //* Overridable method
    //* エラー時の動作を指定する
    error: function(){
        if (this.errorMessage != undefined) {
            alert(this.errorMessage);
        }
        else 
            if (this.message != undefined) {
                alert(this.message);
            }
            else {
                alert("Playground Error");
            }
        return false;
    },
    
    //* Overridable method
    //* 警告時の動作を指定する
    warning: function(){
        if (this.warningMessage != undefined) {
            alert(this.warningMessage);
        }
        else 
            if (this.message != undefined) {
                alert(this.message);
            }
            else {
                alert("Playground Warning");
            }
        return true;
    },
    
    //* Overridable method
    //* 成功時の動作を指定する
    ok: function(){
        return true;
    },
    
    //* Overridable method
    //* 他ステータス時の動作を指定する
    other: function(){
        alert("Playground Error: Unknown status error");
        return false;
    },
    
    //* 制限回数エラーかどうかを調べる
    isLimitationError: function(){
        if (this.message.include(this.LIMITATION_ERROR_MESSAGE)) 
            return true;
        else 
            return false;
    },
    
    //* 残り制限回数がわずかかどうかを調べる
    isLimitationWarning: function(){
        if (this.message.include(this.LIMITATION_WARNING_MESSAGE)) 
            return true;
        else 
            return false;
    }
};

//* イベントを強制的に発火する
EventDispatcher.prototype = {

    click: function(DOMObject){
		
        if (document.createEvent) {
        
            //* Firefox用
            
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click", true, true, window,
				 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            
            DOMObject.dispatchEvent(evt);
        } else {
			
			//* IE用
			
            var evt = document.createEventObject();
            evt.element = function(){
                return evt.srcElement;
            }
            
            DOMObject.fireEvent('onClick', evt);
        }
    },
	
	change: function(DOMObject){
		
        if (document.createEvent) {
        
            //* Firefox用
            
            var evt = document.createEvent("HTMLEvents"); 
            evt.initEvent("change", true, true, window,
				 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            
            DOMObject.dispatchEvent(evt);
        } else {
			
			//* IE用
			
            var evt = document.createEventObject();
            evt.element = function(){
                return evt.srcElement;
            }
            
            DOMObject.fireEvent('onChange', evt);
        }
    }
}

BrowserIdentifier = {
	getBrowserName: function(){
		//* 順番には意味がある 例) Google Chrome は Safari のレンダリングエンジンを使っている等
		if(/opera/i.test(navigator.userAgent)) return 'Opera';  
		else if(/msie/i.test(navigator.userAgent)) return 'Internet Explorer';  
		else if(/chrome/i.test(navigator.userAgent)) return "Google Chrome";  
		else if(/safari/i.test(navigator.userAgent)) return "Safari";  
		else if(/firefox/i.test(navigator.userAgent)) return "Firefox";  
		else if(/gecko/i.test(navigator.userAgent)) return "Gecko";  
		else return navigator.userAgent;  
	},
	
	getBrowserDetail: function(){
		return navigator.userAgent;
	},
	
	isIE: function(){
		return BrowserIdentifier.getBrowserName() == 'Internet Explorer';
	},
	
	isIE6: function(){
		if(/msie 6/i.test(navigator.userAgent)) return true;
		else false;
	},
	
	isIE7: function(){
		if(/msie 7/i.test(navigator.userAgent)) return true;
		else false;
	},
	
	isIE8: function(){
		if(/msie 8/i.test(navigator.userAgent)) return true;
		else false;
	},
	
	isFF: function(){
		return BrowserIdentifier.getBrowserName() == 'Firefox';
	},
	
	isFF2: function(){
		if(/firefox\/2/i.test(navigator.userAgent)) return true;
		else false;
	},
	
	isFF3: function(){
		if(/firefox\/3/i.test(navigator.userAgent)) return true;
		else false;
	},
	
	isSafari: function(){
		return BrowserIdentifier.getBrowserName() == 'Safari';
	},
	
	isOpera: function(){
		return BrowserIdentifier.getBrowserName() == 'Opera';
	},
	
	isChrome: function(){
		return BrowserIdentifier.getBrowserName() == "Google Chrome";  
	},
	
	isGecko: function(){  
		return BrowserIdentifier.getBrowserName() == "Gecko";  
	}
}

function getOrdinalNumber(number){
    var nn = number % 100;
    var n1 = nn % 10;
    var n2 = (nn - n1) / 10
    if (n2 != 1) {
        if (n1 == 1) 
            return number + 'st';
        else 
            if (n1 == 2) 
                return number + 'nd';
            else 
                if (n1 == 3) 
                    return number + 'rd';
                else 
                    return number + 'th';
    }
    else {
        return number + 'th';
    }
}

//* Ajax通信時に返されるエラーコードを扱う関数
function handleHTTPStatusCode(httpObj){
	var description = '';
	switch(httpObj.status){
		case 500: description = "please report this error to Language Grid Playground developers (playground@langrid.org)."; break;
		case 502: description = "please retry your action."; break;
		case 504: description = "please check your proxy setting."; break;
	}
	alert(httpObj.status+' '+httpObj.statusText+': '+description);
}
