/**
 *  ABook Viewer for WEB
 *	Common Library
 *  Copyright (C) Agentec Co, Ltd. All rights reserved.
 */

/*
 * User Environment Check Class
 */
var UserEnvironment = function() {
		
	this.appName = navigator.appName;
	this.userAgent = navigator.userAgent;
	this.os = checkOS(this.userAgent);
	this.browser = checkBrowser(this.userAgent);
	
	/* windows os check */
	this.isWindows = function() {
		return (this.os == "windows");
	};
	/* mac os check */
	this.isMac = function() {
		return (this.os == "mac");
	};
	
	/* ipad check */
	this.isIpad = function() {
		return (this.os == "ipad");
	};
	
	/* iphone check */
	this.isIphone = function() {
		return (this.os == "iphone");
	};
	/* android check */
	this.isAndroid = function() {
		return (this.os == "android");
	};
	/** check operating system */	
	function checkOS(userAgent) {
		if(userAgent.toLowerCase().indexOf("windows") >= 0) {
			return "windows";
		}
		if(userAgent.toLowerCase().indexOf("mac") >= 0) {
			if(userAgent.toLowerCase().indexOf("ipad") >= 0) {
				return "ipad";
			}
			if(userAgent.toLowerCase().indexOf("iphone") >= 0) {
				return "iphone";
			}
			return "mac";
		}
		if(userAgent.toLowerCase().indexOf("android") >= 0) {
			return "android";
		}
		return "unknown";
	};
	/** check user browser */
	function checkBrowser(userAgent) {
		if(userAgent.toLowerCase().indexOf("msie") >= 0) {
			return "msie";
		}
		if(userAgent.toLowerCase().indexOf("firefox") >= 0) {
			return "firefox";
		}
		if(userAgent.toLowerCase().indexOf("safari") >= 0) {
			if(userAgent.toLowerCase().indexOf("chrome") >= 0) {
				return "chrome";
			}
			return "safari";
		}
		if(userAgent.toLowerCase().indexOf("opera") >= 0) {
			return "opera";
		}
		return "unknown";
	};
};
/*
 * User Settings Class Definition
 */
var UserSetting = function() {
	this.US_KEY="AVWUS";
	this.userSetting = this.load();
};
/* get user setting from localStorage */
UserSetting.prototype.load = function () {
    var storage = window.localStorage;
    var value = null;
    var js = null;
    if (storage) {
        var value = storage.getItem(this.US_KEY);
        if (!value) {
            value = "{}"; // 空JSON文字列
        }
        js = JSON.parse(value);
    }
    return js;
};
/* store user setting */
UserSetting.prototype.set = function(key, value) {
	if(!this.userSetting) {
		this.userSetting = this.load();
	}
	var values = this.userSetting;
	if(!values) {
		values = { key: value };
	} else {
		values[key] = value;
	}
	var storage = window.localStorage;
	if(storage) {
		var jsonStr = JSON.stringify(values);
		storage.setItem(this.US_KEY, jsonStr);
	}
	this.userSetting = values;
};
/* grab user setting */
UserSetting.prototype.get = function(key) {
	if(!this.userSetting) {
		this.userSetting = this.load();
	}
	var values = this.userSetting;
	if(values) {
		return values[key];
	}
	return null;
};
/* show user setting object list */
UserSetting.prototype.show = function(elmid) {
	var storage = window.localStorage;
	var tags = "<p>";
	if(storage) {
		var value = storage.getItem(this.US_KEY);
		if(value) {
			var js = JSON.parse(value);
			$.each(js, function(k, v) {
				tags = tags + "<b>" + k + "</b>:" + v + "<br />";									
			});
		}
		tags = tags + "</p>";
		$(elmid).html(tags);
	}	
};
/* ユーザ設定のキーリストを取得 */
UserSetting.prototype.keys = function() {
	var storage = window.localStorage;
	var keyList = [];
	if(storage) {
		var value = storage.getItem(this.US_KEY);
		if(value) {
			var js = JSON.parse(value);
			var i = 0;
			$.each(js, function(k, v) {
				keyList[i++] = k;
			});
		}
		return keyList;
	}
	return null;
};
/* ユーザ設定を削除 */
UserSetting.prototype.remove = function(key) {
	var storage = window.localStorage;
	if(storage) {
		var value = storage.getItem(this.US_KEY);
		if(value) {
			var js = JSON.parse(value);
			if(js) {
				delete js[key];
				storage.setItem(this.US_KEY, JSON.stringify(js));
			}
		}
	}
};
/* ユーザ設定をすべて削除 */
UserSetting.prototype.removeAll = function() {
	var storage = window.localStorage;
	if(storage) {
		storage.remove(this.US_KEY);
	}	
};

/*
 * User Session Class Definition
 */
var UserSession = function() {
	this.available = false;
};
/* Initialize User Session */
UserSession.prototype.init = function(option) {
	
	this.available = false;
	if(option == 'restore') {
		var value = null;
		try {
			value = this._get('init');
		} catch(e) {
			value = null;
		} finally {
			if(value) {
				this.available = true;
			}
		}
	} else {
		this.set("init", new Date().toLocaleString());
		this.available = true;		
	}
};
/* store key, value item to user session */
UserSession.prototype.set = function(key, value) {
	var storage = window.sessionStorage;
	if(storage) {
		if(this.available == false) {
			if(key == "init") {
				storage.setItem("AVWS_" + key, value);				
			} else {
				throw new Error("Session destoryed.");
			}
		} else {
			storage.setItem("AVWS_" + key, value);
		}
	}	
};
/* get session item value */
UserSession.prototype.get = function(key) {
	var value = null;
	if(this.available) {
		value = this._get(key);			
	} else {
		throw new Error("Session Destroyed.");		
	}
	return value;	
};
/* get item value from session storage */
UserSession.prototype._get = function(key) {
	var storage = window.sessionStorage;
	var value = null;
	if(storage) {
		value = storage.getItem("AVWS_" + key);			
	}
	return value;		
};
/* destroy user session */
UserSession.prototype.destroy = function() {
	var storage = window.sessionStorage;
	if(storage) {
		storage.clear();
		this.available = false;
	}	
};
/* show user session object list */
UserSession.prototype.show = function(elmid) {
	var storage = window.sessionStorage;
	var tags = "<p>";
	if(storage) {
		for(var i = 0; i < storage.length; i++) {
			var key = storage.key(i);
			var value = storage.getItem(key);
			tags = tags + "<b>" + key + "</b>:" + value + "<br />";
		}
		tags = tags + "</p>";
		$(elmid).html(tags);
	}	
};
/*
 * Variables
 */
var avwUserSessionObj = null;
var avwUserSettingObj = null;
var avwUserEnvObj = null;
var avwSysSettingObj = null;

/* Initialize system */
$(function () {
	
    // システム設定ファイルの配置先パスの決定
	var location = window.location.toString().toLowerCase();
	var sysFile = '';
	if (location.indexOf('/abvw') < 0) {
 		sysFile = './abvw/common/json/sys/conf.json';
 	} else {
        sysFile = './common/json/sys/conf.json';
	}

    // システム設定ファイルを読み込む
    $.ajax({
        url: sysFile,
        async: false,
        cache: false,
        dataType: 'json',
        success: function (data) {
            avwSysSettingObj = data;
        },
        error: function (xmlHttpRequest, txtStatus, errorThrown) {
            var error = 'Could not load the system configuration file. Please check it.';
            error += '\n' + xmlHttpRequest.status + ' ' + txtStatus + ' ' + errorThrown + ' : ' + sysFile;
            alert(error);
        }
    });
    
    // ロード時に一旦エラー状態をクリアしておく
    avwClearError();
});

/* get system setting object */
function avwSysSetting() {
	return avwSysSettingObj;
};

/* get user environment object */
function avwUserEnv() {
	if(avwUserEnvObj == null) {
		avwUserEnvObj = new UserEnvironment();
	}
	return avwUserEnvObj;
};
/* get user session object */
function avwUserSession() {
	if(!avwUserSessionObj) {
		var obj = new UserSession();
		obj.init('restore');
		if(obj.available) {
			avwUserSessionObj = obj;
			return avwUserSessionObj;
		} else {
			return null;
		}
	}
	return avwUserSessionObj;
};
/* create user session object */
function avwCreateUserSession() {
	if(avwUserSessionObj) {
		avwUserSessionObj.destroy();
	} else {
		avwUserSessionObj = new UserSession();		
		avwUserSessionObj.init();
	}
	return avwUserSessionObj;
};
/* check Login or not */
function avwCheckLogin(option) {
	var userSession = avwUserSession();
	if(!userSession) {

		/* エラー画面を表示 */
		var tags = '<div id="avw-auth-error">' +
				   '<div style="display:table; width:100%; height:100%;">' + 
				   '<div style="display:table-cell; text-align:center; vertical-align:middle;">' +
				   '<p><h4>認証エラー</h4>ログインしてからご利用ください。</p>' + 
				   '<div><button id="avw-unauth-ok">OK</button></div>' +
				   '</div></div></div>';
		$('body').prepend(tags);
		$('#avw-auth-error').css({		    
		    'opacity': 1,
		    'position': 'fixed',
		    'top': '0',
		    'left': '0',
		    'width': $(window).width(),
		    'height': $(window).height(),
		    'zIndex': '10000'
		});
		// resize error page	
		$(window).resize(function() {
			$('#avw-auth-error').css( {
				'width': $(window).width(),
				'height': $(window).height()
			});			
		});
			
		var returnPage;
		if(option) {
			returnPage = option
		} else {
			var sysSetting = avwSysSetting();
			returnPage = sysSetting.loginPage;
		}
		/* ログイン画面に戻る */
		$('#avw-unauth-ok').click(function() {
			window.location = returnPage;		
		});		
		return false;
	}
	return true;
};
/* get user setting object */
function avwUserSetting() {
	if(avwUserSettingObj == null) {
		avwUserSettingObj = new UserSetting();
	}
	return avwUserSettingObj;
};

/* String.format function def. */
function format(fmt) {
  for (var i = 1; i < arguments.length; i++) {
      var reg = new RegExp("\\{" + (i - 1) + "\\}", "g");
    fmt = fmt.replace(reg,arguments[i]);
  }
  return fmt;
};

/* CMS API Call(async. call) */
function avwCmsApi(accountPath, apiName, type, params, success, error) {
	var sysSettings = avwSysSetting();
	_callCmsApi(sysSettings.apiUrl, accountPath, apiName, type, params, true, success, error);
};
/* CMS API Call(sync. call) */
function avwCmsApiSync(accountPath, apiName, type, params, success, error) {
	var sysSettings = avwSysSetting();
	_callCmsApi(sysSettings.apiUrl, accountPath, apiName, type, params, false, success, error);
};
/* CMS API Call(async. call) */
function avwCmsApiWithUrl(url, accountPath, apiName, type, params, success, error) {
	_callCmsApi(url, accountPath, apiName, type, params, true, success, error);
};
/* CMS API Call(sync. call) */
function avwCmsApiSyncWithUrl(url, accountPath, apiName, type, params, success, error) {
	_callCmsApi(url, accountPath, apiName, type, params, false, success, error);
};

/* CMS API Call */
function _callCmsApi(url, accountPath, apiName, type, params, async, success, error) {
	
	// アプリケーション設定取得
	var sysSettings = avwSysSetting();
	
	// url 構築
	var apiUrl;
	if(!url) {
		apiUrl = sysSettings.apiUrl;
	} else {
		apiUrl = url;
	}
	if(accountPath) {
		apiUrl = format(apiUrl, accountPath)	
	}
	apiUrl = apiUrl + '/' + apiName + '/';
	
	//----------------------------------------------------------------------------------
	// for IE: 暫定的に対応 (これをすることでIE9でもCrossDomainリクエストが可能だがアクセスのたびに警告が出る)
	$.support.cors = true;
	//----------------------------------------------------------------------------------
	
	// ajax によるAPIの実行(json)
	$.ajax( {
		async:		(async) ? async : false,
		type:		(type) ? type : 'get',
		url:		apiUrl,
		cache: 		false,
		dataType:	'json',
		data:		params,
		crossDomain: true,
		beforeSend:	function(xhr) {
			/*
			 * ABook viewer for WEB 用のリクエストヘッダに、以下のヘッダを付加する
			 * X-AGT-AppId: ABookWebCL
			 * X-AGT-AppVersion: 0.0.1
			 */
			xhr.setRequestHeader('X-AGT-AppId', sysSettings.appName);
			xhr.setRequestHeader('X-AGT-AppVersion', sysSettings.appVersion);
		},
		success:	function(data) {
			if(success) {
				success(data);				
			}
		},
		error:		function(xmlHttpRequest, txtStatus, errorThrown) {
			/* call custom error process */
			if(error) {
				error(xmlHttpRequest, txtStatus, errorThrown);
			} else {
				showSystemError();
			}
		}
	});	
};

/*
 * Create Image Data Scheme URI
 */
var ImageDataScheme = function () {

    // バイナリデータを文字列に変換
    this.convBinaryToString = function (filestream) {
        var bytes = [];
        for (var i = 0; i < filestream.length; i++) {
            bytes[i] = filestream.charCodeAt(i) & 0xff;
        }
        return String.fromCharCode.apply(String, bytes);
    };

    // 画像のバイト文字列をdataスキームURIに変換
    this.convImageToDataScheme = function (binaryData, ie) {
        var b64Data;
        var imgHeader;
        var imgType = 'png';

        if (ie) {
            // binary to base64 for ie
            b64Data = this.base64encodeForIE(binaryData);
        } else {
            // binary to base64 for FF, Chrome, Safari
            var bin = this.convBinaryToString(binaryData);
            b64Data = btoa(bin);
            imgHeader = bin.substring(0, 9);
            imgType = this.checkImageType(imgHeader);
        }
        return 'data:image/' + imgType + ';base64,' + b64Data;
    };

    // 画像タイプ(種類をチェック)
    this.checkImageType = function (header) {
        if (header.match(/^\x89PNG/)) {
            return 'png';
        } else if (header.match(/^GIF87a/) || header.match(/^GIF89a/)) {
            return 'gif';
        } else if (header.match(/^\xff\xd8/)) {
            return 'jpeg';
        } else {
            // デフォルトはPNG画像として扱う
            return 'png';
        }
    };

    // バイナリデータをBase64文字列に変換する(IE専用)
    this.base64encodeForIE = function (binaryData) {
        // 新規XMLデータを作成
        var xml = new ActiveXObject("Microsoft.XMLDOM");
        xml.loadXML('<?xml version="1.0" ?> <root/>');
        xml.documentElement.setAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");

        // バイナリデータを格納するためのノードを作成
        var node = xml.createElement("file-node");
        node.dataType = "bin.base64";

        // バイナリデータを格納
        node.nodeTypedValue = binaryData;
        xml.documentElement.appendChild(node);

        // そのノードからBASE64エンコード済み文字列を取り出す
        var base64encoded_text = node.text;
        return base64encoded_text;
    };
};

/* Grab Content Page Image Function
 * <parameters>
 * 	accountPath: accountPath
 * 	params: request parameters (data type: json, see below)
 * 			{ 'sid': sid, contentId: 'contentId', pageNo: 'pageNo' }
 * 	success: function(string: this is image binary encoded string)
 * 	error: function(XMLHttpRequest, XMLHttpRequest.status, XMLHttpRequest.statusText)
 */
function avwGrabContentPageImage(accountPath, params, success, error) {

	// API実行準備
	var sysSettings = avwSysSetting();
	var apiName = 'webContentPageImage';	// API名

	//url 構築
	var apiUrl;
	apiUrl = sysSettings.apiUrl;
	if(accountPath) {
		apiUrl = format(apiUrl, accountPath)
	}
	apiUrl = apiUrl + '/' + apiName + '/';

	// 送信パラメータの構築
	var requestParams = 'contentId=' + params.contentId + '&sid=' + params.sid + '&pageNo=' + params.pageNo + '&pid=' + params.pid;
	//apiUrl += '?' + requestParams;
	apiUrl += '?' + requestParams + '&isBase64=true';
	
	// バイナリ形式で画像イメージを取得し、Base64にエンコードする
	var xmlHttp;
	var ie = false;
	if(window.ActiveXObject) {
		xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
		ie = true;
	} else {
		xmlHttp = new XMLHttpRequest();
	}
	xmlHttp.open('get', apiUrl);
	xmlHttp.setRequestHeader('X-AGT-AppId', sysSettings.appName);
	xmlHttp.setRequestHeader('X-AGT-AppVersion', sysSettings.appVersion);
	/*
	if(xmlHttp.overrideMimeType) {
		// for FF, Chrome, Safari
		xmlHttp.overrideMimeType('text/plain; charset=x-user-defined');		
	}
	*/
	xmlHttp.onreadystatechange = function () {
	    if (xmlHttp.readyState == 4) {
	        if (xmlHttp.status == 200) {
	            /*
	            //base64 encode
	            var ids = new ImageDataScheme();
	            var src;	// Image Data URI
				
	            if(ie) {
	            // for IE
	            src = ids.convImageToDataScheme(xmlHttp.responseBody, ie);
	            } else {
	            // for FF, Chrome, Safari
	            src = ids.convImageToDataScheme(xmlHttp.responseText, ie);					
	            }
	            */
	            var src; // Image Data URI
	            /*
	            if(ie) {
	            // for IE
	            src = 'data:image/png;base64,' + xmlHttp.responseBody;
	            } else {
	            // for FF, Chrome, Safari
	            src = 'data:image/png;base64,' + xmlHttp.responseText;					
	            }
	            */
	            src = 'data:image/png;base64,' + xmlHttp.responseText;

	            if (success) {
	                success(src);
	            }
	        } else {
	            if (error) {
	                error(xmlHttp, xmlHttp.status, xmlHttp.statusText);
	            } else {
	                console.log(xmlHttp.status + ' ' + xmlHttp.statusText);
	            }
	        }
	    }
	};
	xmlHttp.send();
};

/*
 * file upload function: call uploadBackupFile API
 * <params>
 * [
 * 	{ name: 'sid', content: 'content' }
 * 	{ name: 'deviceType', content: '4' }
 * 	{ name: 'formFile', fileName: 'filename', contentType: 'text-plain' }
 * ]
 */
function avwUploadBackupFile(accountPath, params, async, success, error) {
	
	/* API実行準備*/
	var sysSettings = avwSysSetting();
	var apiName = 'uploadBackupFile';	// API名
	
	//url 構築
	var apiUrl;
	apiUrl = sysSettings.apiUrl;
	if(accountPath) {
		apiUrl = format(apiUrl, accountPath)
	}
	apiUrl = apiUrl + '/' + apiName + '/';
	
	/* POST(multipart/form-data)送信準備 */
	var body = '';
	var boundary = '';

	// boundaryを構築
	var date = new Date();
	boundary = '------------------------' + date.getMilliseconds() 
				+ (date.getMonth() + 1)
				+ date.getMinutes()
				+ date.getFullYear()
				+ date.getDay()
				+ date.getHours()
				+ date.getSeconds();
	
	// bodyを構築
	for(var i = 0; i < params.length; i++) {
		var item = params[i];
		body += '--' + boundary + '\r\n';	
		body += 'Content-Disposition: form-data; name="' + item.name + '"';
		if(item.fileName) {
			body += '; filename="' + item.fileName + '"\r\n';
		} else {
			body += '\r\n';
		}
		if(item.contentType) {
			body += 'Content-Type="' + item.contentType + '"\r\n';
		}
		body += '\r\n';
		body += item.content + '\r\n';
	}
	body += '--' + boundary + '--\r\n';
	
	// ajax によるAPIの実行(json)
	$.ajax( {
		async:		(async) ? async : false,
		type:		'post',
		url:		apiUrl,
		data:		body,
		beforeSend:	function(xhr) {
			/*
			 * ABook viewer for WEB 用のリクエストヘッダに、以下のヘッダを付加する
			 * X-AGT-AppId: ABookWebCL
			 * X-AGT-AppVersion: 0.0.1
			 */
			xhr.setRequestHeader('X-AGT-AppId', sysSettings.appName);
			xhr.setRequestHeader('X-AGT-AppVersion', sysSettings.appVersion);
			
			/*
			 * uploadBackupFileは multipart/form-data でPOST送信する
			 */
            xhr.setRequestHeader('Content-Type', 'multipart/form-data; boundary=' + boundary);
            //xhr.setRequestHeader('Content-Length', getByte(body));
		},
		success:	function(data) {
			if(success) {
				success(data);				
			}
		},
		error:		function(xmlHttpRequest, txtStatus, errorThrown) {
			/* call custom error process */
			if(error) {
				error(xmlHttpRequest, txtStatus, errorThrown);
			} else {
				showSystemError();
			}
		}
	});	
};
/* get bytes of text */
function getByte(text) {
	count = 0;
	for (i=0; i<text.length; i++) {
		n = escape(text.charAt(i));
		if (n.length < 4) {
			count++;
		}
		else {
			count+=2;
		}
	}
	return count;
};
/* show system error message */
var hasErrorKey = 'AVW_HASERR';
function showSystemError() {
	
	if(avwHasError()) {
		// すでにエラー状態であればエラーを表示しない
		return;
	} else {
		// エラー状態にセット
		avwSetErrorState();
	}
	
	// create DOM element for showing error message
	var errMes = i18nText('sysErrorCallApi01');
	var tags = '<div id="avw-sys-error"></div>';
	//$('body').prepend(tags);
	$('body').append(tags);
	$('#avw-sys-error').css({
	    'opacity': 0.7,
	    'position': 'fixed',
	    'top': '0',
	    'left': '0',
	    'width': $(window).width(),
	    'height': $(window).height(),
	    'background': '#999',
	    'z-index': 90000
	});
	// resize error page	
	$(window).resize(function() {
		$('#avw-sys-error').css( {
			'width': $(window).width(),
			'height': $(window).height()
		});			
	});
	// show error messages
	$().toastmessage({ position: 'middle-center' });
	$().toastmessage('showToast', {
		type: 'error',
		sticky: true,
		text: errMes
	});				
/*
	$().toastmessage('showToast', {
		type: 'error',
		sticky: true,
		text: errMes,
		close: function() { isShowErrorMessage = false; }
	});				
*/
};
/* エラー状態を取得 */
function avwHasError() {
	var session = window.sessionStorage;
	var isError = false;
	if(session) {
		isError = session.getItem(hasErrorKey);
	}
	return (isError == 'true');
};
/* エラー状態にセット */
function avwSetErrorState() {
	var session = window.sessionStorage;
	if(session) {
		session.setItem(hasErrorKey, true);
	}
};
/* エラー状態をクリア */
function avwClearError() {
	var session = window.sessionStorage;
	if(session) {
		session.setItem(hasErrorKey, false);
	}
};
/* ブラウザunload時に警告メッセージの出力設定を行う関数 */
function avwSetLogoutNortice() {
	window.onbeforeunload = function(event) {
		// メッセージ表示
		// FFでは、https://bugzilla.mozilla.org/show_bug.cgi?id=588292 によりメッセージが出力されない
		var message = i18nText('sysInfoWithoutLogout');
		var e = event || window.event;
		if(e) {
			e.returnValue = message;
		} 
		return message;		
	};
};
/* 警告メッセージを出力しないでページ遷移を行う関数 */
function avwScreenMove(url) {
	window.onbeforeunload = null;
	window.location = url;
};
/* Debug Log */ 
function avwLog(msg) {
	if(avwSysSetting().debug) {
		console.log(msg);		
	}
};