var bant = {
	isOk: function(){
		try{
			return window.external.bant.isOk();
		}
		catch(err){
			return false;
		}
		return false;
	},
	WebSocket: function(url, protocols){
		if(protocols === undefined)
			protocols = '';
		if(!Array.isArray(protocols))
			protocols = [protocols];
		protocols = protocols.join();
		this._instance = window.external.bant.websocket.create(this, url, protocols);
	},
	log: {
		debug: function(text){return window.external.bant.log('debug', text);},
		info: function(text){return window.external.bant.log('info', text);},
		warning: function(text){return window.external.bant.log('warning', text);},
		error: function(text){return window.external.bant.log('error', text);}
	},
	getVersion: function(){
		return '3.0';
	},
	execute: {
		uri: function(sender, uri){
			return window.external.bant.execute.uri(sender, uri);
		},
		linktarget: function(target, parameters){
			if(parameters === undefined)
				parameters = '';
			return window.external.bant.execute.linktarget(target, parameters);
		}
	},
	utils:{
		addFiles: function(sender){
			return window.external.bant.utils.addFiles(sender);
		},
		is_in: function(item, arr){
			for(var i=0;i < arr.length; ++i){
				if(arr[i] == item)
					return true;
			}
			
			return false;
		},
		is_in_no_case: function(item, arr){
			for(var i=0;i < arr.length; ++i){
				if(arr[i].toLowerCase() == item.toLowerCase())
					return true;
			}
			
			return false;
		}
	},
	callback:{
		dialog:{
			// return empty json data
			onClose: function(data){return true;},
			// should return true or false
			onShow: function(){return true;}
		},
		clipboard:{
			onText: function(text){return true;},
			onLicenseKey: function(licenseKey){return true;},
			onEMailAddress: function(emailaddress){return true;}
		},
		download:{
			onCompleted: function(data){return true;},
			onAborted: function(data){return true;}
		}
	},
	resources:{
		get: function(ensureExists){
			if(ensureExists === undefined)
				ensureExists = '*';
			return JSON.parse(window.external.bant.resources.get(ensureExists));
		},
		set: function(data){
			return window.external.bant.resources.set(JSON.stringify(data));
		},
		setup:{
			getTitle: function(sender){ return bant.resources.load(sender, 'setup.title', '### SETUP.TITLE ###'); }
		}
	},
	service: {
		update: {
			execute: function(sender){return window.external.bant.service.update.execute(sender);},
			exists: function(){return window.external.bant.service.update.exists();}
		},
		upgrade: {
			exists: function(){return window.external.bant.service.upgrade.exists();},
			execute: function(sender){return window.external.bant.service.upgrade.execute(sender);},
			info: {
				execute: function(){return window.external.bant.service.upgrade.info.execute();}
			}
		},
		sendFeedback: function(sender, data){
			if(sender === undefined)
				sender = null;
			
			if(data === undefined)
				data = {};
			
			return window.external.bant.service.sendFeedback(sender, JSON.stringify(data));
		}
	},
	license:{
		update: function(license){
			return JSON.parse(window.external.bant.license.update(JSON.stringify(license)));
		},
		isValid: function(license){
			return window.external.bant.license.isValid(JSON.stringify(license));
		}
	},
	button:{
		click: function(sender, id){ return window.external.bant.button.click(sender, id); }
	},
	dialog:{
		close: function(sender, id){ return window.external.bant.dialog.close(sender, id); },
		load: function(id_uri, fallbackId){ return window.external.bant.dialog.load(id_uri, fallbackId); },
		layout_min: function(w, h){
			var result_w = w;
			var result_h = h;
			var all = document.body.getElementsByTagName('*');
			for (var i=0, max=all.length; i < max; i++) {
				var rect = all[i].getBoundingClientRect();
				if(rect.right > result_w){
					result_w = parseInt(rect.right);
				}
				if(rect.bottom > result_h){
					result_h = parseInt(rect.bottom);
				}
			}
			return window.external.bant.dialog.layout(result_w, result_h);
		},
		layout: function(){
			return bant.dialog.layout_min(0,0);
		},
		center: function(){
			return window.external.bant.dialog.center();
		},
		getX: function() { return window.external.bant.dialog.getX(); },
		getY: function() { return window.external.bant.dialog.getY(); },
		setPosition: function(x,y) { return window.external.bant.dialog.setPosition(x,y); },
		getHeight: function() { return window.external.bant.dialog.getHeight(); },
		getWidth: function() { return window.external.bant.dialog.getWidth(); },
		setSize: function(w,h) { return window.external.bant.dialog.setSize(w,h); },
		startDrag: function(sender, event){ return window.external.bant.dialog.startDrag(sender, event); },
		localize: function(){
			var language = bant.resources.get('product').language;
			var all = document.body.getElementsByTagName('*');
			for (var i=0, max=all.length; i < max; i++) {
				var element = all[i];
				if(element!=null && element.hasAttribute('data-localize-id')){
					var id = element.getAttribute('data-localize-id');
					if(bant.utils.is_in_no_case(element.tagName, ["h1", "h2", "h3", "h4", "h5", "h6", "a", "div", "span", "label", "button", "textarea", "p"])){
						element.innerText = window.external.bant.dialog.localize(element, id, element.innerText);
					}
					
					if(element.hasAttribute('title')){
						element.setAttribute('title', window.external.bant.dialog.localize(element, id+'.title', element.getAttribute('title')));
					}
					
					if(element.hasAttribute('placeholder')){
						element.setAttribute('placeholder', window.external.bant.dialog.localize(element, id+'.placeholder', element.getAttribute('placeholder')));
					}
					
					element.setAttribute("lang", language);
				}
			}
		}
	}
};
bant.WebSocket.prototype.send = function(data){
	window.external.bant.websocket.send(this._instance, data);
};
bant.WebSocket.prototype.close = function(code, reason){
	if(code === undefined)
		code = 1000;
	if(reason === undefined)
		reason = '';
	window.external.bant.websocket.close(this._instance, code, reason);
};
bant.WebSocket.prototype._onopen = function(){
	return this.onopen();
};
bant.WebSocket.prototype.onopen = function(){};

bant.WebSocket.prototype._onmessage = function(data){
	evt = {};
	evt.data = data;
	return this.onmessage(evt);
};
bant.WebSocket.prototype.onmessage = function(evt){};

bant.WebSocket.prototype._onerror = function(){
	evt = {};
	return this.onerror(evt);
};
bant.WebSocket.prototype.onerror = function(evt){};

bant.WebSocket.prototype._onclose = function(code, reason, wasClean){
	evt = {};
	evt.code = code;
	evt.reason = reason;
	evt.wasClean = wasClean;
	return this.onclose(evt);
};
bant.WebSocket.prototype.onclose = function(){};