(function(window){
	var atto = window.atto = {};
	
	/**
	 * 로딩된 javascript 의 Name 을 Map 형태로 갖고 있는 변수
	 * key {string} ex) 'atto.util.Paging'
	 * value {boolean} true
	 */
	var _included = {}; 
	
	/**
	 * 해당 객체의 javascript 파일을 로드한다.
	 * @param target {string} 로드할 객체의 이름
	 * @param dyn {boolean} script 태그를 동적으로 생성
	 * @private
	 */
	function _load(target, dyn) {
		var path = target.replace(/\./g, '/') + '.js';
		if (dyn) {
			var script = document.createElement('script');
			script.type = 'text/javascript';
			script.src = '/js/' + path;
			document.getElementsByTagName("head")[0].appendChild(script);
		} else {
			document.write('<script src="/js/' + path + '" type="text/javascript"></script>');
		}
	}
	
	/**
	 * 네임스페이스 제공 함수
	 * 주어진 네임스페이스가 존재하는 지 확인 한 후 없으면 
	 * 빈 객체를 생성하여 네임스페이를 만든다.
	 * @param name {string} 
	 * @param fn {function} 실행될 함수
	 */
	atto.ns = function(name, fn){
		if (name) {
			var parts = name.split('.');
			var base = window;
			$.each(parts, function(idx, part){
				if (typeof base[part] === 'undefined') {
					base[part] = {};
				}
				base = base[part];
			});
			if ($.isFunction(fn)) {
				fn.call(base, base);
			}
		}
	};
	
	/**
	 * 주어진 이름의 javascript 가 현재 로드되었는지 확인하고
	 * 없으면 해당 객체의 javascript 를 로드한다.
	 */
	atto.require = function(target, dyn) {
		if (!_included[target]) {
			_included[target] = true;
			_load(target, dyn);
		}
	};
	
	/**
	 * 클래스 상속
	 */
	atto.extend = function(superClass, subClass, proto) {
		var F = function() {};
		F.prototype = superClass.prototype;
		subClass.prototype = new F();
		subClass.prototype.constructor = subClass;
		$.extend(subClass.prototype, proto);
	};
	
	/**
	 * 대기중인 함수 Array
	 * {fn:function, require:{string, boolean}, count:{number}} 
	 * 형식의 객체를 담는다.
	 */
	var _deferFunctions = [];
	
	/**
	 * 대기중인 Object 의 name 을 저장할 Map
	 */
	var _deferNameMap = {};
	
	/**
	 * defer 체크를 위한 Timer ID
	 */
	var _checkDeferTimer;
	
	/**
	 * name에 해당하는 객체가 존재할때까지 대기하다가 (타이머)
	 * 생성된 후에 fn 을 실행한다. 
	 */
	atto.defer = function(names, fn){
		var reqMap = {};
		var count = 0;
		$.each(names, function(idx, name){
			if (!_isObjectExist(name)) {
				_deferNameMap[name] = true;
				reqMap[name] = true;
				count++;
			}
		});
		if (count > 0) {
			_deferFunctions.push({
				fn : fn,
				require : reqMap,
				count : count
			});
		} else {
			fn.call();
		}
		
		if (!_checkDeferTimer) {
			_checkDeferTimer = window.setInterval(_checkDeferredFunction, 300);
		}
	};
	
	/**
	 * 구글맵 로드 상태 
	 * (0:요청전, 1:응답대기중, 2:jsApi로드됨, 3:로드완료)
	 */
	var _googleMapStatus = _isObjectExist('google.maps') ? 3 : 0; //
	
	/**
	 * 구글맵 로드시 실행될 함수들
	 */
	var _googleMapFunctions = [];
	
	/**
	 * 구글 jsapi 완료시 현재 위치를 업데이트 할 지 여부
	 */
	var _bUpdateRegion = false;
	
	/**
	 * name 에 해당하는 Object가 존재하는지 여부를 반환
	 */
	function _isObjectExist(name){
		var base = window;	
		var parts = name.split('.');
		var exist = true;
		$.each(parts, function(idx, part){
			if (typeof base[part] === 'undefined') {
				exist = false;
				return false;
			} else {
				base = base[part];	
			}
		});
		return exist;
	}
	
	/**
	 * 구글 지도가 로드될때까지 대기 후 fn을 실행시킨다. 
	 */
	atto.googleMaps = function(fn) {
		if (_googleMapStatus==3) {
			fn.call();			
		} else {
			if (_googleMapStatus==0) {
				_googleMapStatus = 1;
				var script = document.createElement('script');
				script.src = 'http://www.google.com/jsapi?key=ABQIAAAAgKS0aAkG4ayNaezO1nG0ehRkFNBi9n2XDRzMgvgM1Ek7_GldkRQ7NdSDNNsTL2NNtUDThqchSMWTKg&callback=atto.loadGoogleMaps';
				document.getElementsByTagName("head")[0].appendChild(script);
			}
			_googleMapFunctions.push(fn);	
		}
	};
	
	/**
	 * 구글 jsapi 가 로드된 후 호출하게될 함수명. (직접호출용이 아님. 외부에서 호출)
	 */
	atto.loadGoogleMaps = function(){
		_googleMapStatus = 2;
		google.load('maps', 2, {
			callback : function(){
				_googleMapStatus = 3;
				$.each(_googleMapFunctions, function(idx, fn) {
					fn.call();
				});
			}
		});
		
		if (_bUpdateRegion && 
			google.loader.ClientLocation &&
			google.loader.ClientLocation.address.country_code &&
			google.loader.ClientLocation.address.region) {
				$.post('/member/updateRegion.json', {
					city : google.loader.ClientLocation.address.region
				});
		}
	};
	
	/**
	 * 구글 jsapi 완료시 현재 위치를 업데이트 하도록 설정한다.
	 */
	atto.updateRegion = function() {
		_bUpdateRegion = true;
	};
	
	/**
	 * defer 상태인 함수들의 필요 Object 들이 로드되었는지 확인하고 실행한다. 
	 */
	function _checkDeferredFunction(){
		var finish = true;
		$.each(_deferNameMap, function(name, fnArray) {
			if (_isObjectExist(name)) {
				$.each(_deferFunctions, function(idx, obj){
					if (obj && obj.require[name]) {
						delete obj.require[name];
						obj.count--;
						if (obj.count==0) {
							obj.fn.call();
							_deferFunctions.splice(idx, 1);
						};
					};
				});
				delete _deferNameMap[name];
			} else {
				finish = false;
			}
		});
		if (finish) {
			window.clearInterval(_checkDeferTimer);
			_checkDeferTimer = false;
		}
	}
	
	/**
	 * CSS 동적 로딩
	 */
	atto.loadCSS = function(path){
		var addedPath = path + '?' + new Date().getTime();
		if (document.createStyleSheet){
            document.createStyleSheet(addedPath);
        } else {
        	$('head').append($('<link rel="stylesheet" href="' + addedPath + '" type="text/css" />'));
        }	
	};
	
	_load('atto.console');
	_load('atto.popup');
	_load('atto.layout');
	_load('atto.string');
	_load('atto.command');
	_load('atto.message');
	_load('atto.app.controller');
	
	_load('atto.login');
	_load('atto.confirm');
	_load('atto.Layer');
	_load('atto.AppendList');

	_load('atto.plugin.wait');
	
	$.ajaxSetup({cache:false});
	
	$(window.document).ready(function(){
		// apply png filter		
		if (/MSIE 6/i.test(window.navigator.userAgent)) {
			$('.png24').each(function(idx, el) {
				atto.layout.png24IE(el);
			});
		}
		// init top menu
		$('#header ul.navi>li').mouseenter(function(ev){
			var img = $(this).find('img.nav')[0];
			img.src = img.src.replace('_off.gif', '_on.gif');
			$(this).children('ul').removeClass('hidden');
		}).mouseleave(function(ev){
			var img = $(this).find('img.nav')[0];
			img.src = img.src.replace('_on.gif', '_off.gif');
			$(this).children('ul').addClass('hidden');
		});

		// Session 정보 
		// TODO : 세션 정보 갖고올 다른 방법이 있을까?
		atto.session = {
			uid : $('#header var.uid').text()
		};
	
		// 스마트앱 초기화
		if (atto.session.uid) {
			atto.app.controller.init();
		}
		
		// 로그인이 필요한 링크
		if (!atto.session.uid) {
			$('a.require_login, area.require_login').each(function(idx, el){
				if ($(el).hasClass('message')) {
					$(el).click(function(ev){
						ev.preventDefault();
						atto.message.show('로그인 후 사용가능한 메뉴입니다.');
					});
				} else {
					$(el).click(function(ev){
						ev.preventDefault();
						atto.login.show();
					});
				}
			});
		}
		
		// 화면 전환 효과
		$('#wrapper').delegate('a.go_to_create, area.go_to_create, a.back_to_browse', 'click', function(ev){
			ev.preventDefault();
			if (!atto.session.uid) {
				return;
			}
			var fromURL = location.href.replace(/.+travelro.co.kr[^\/]*/, '');
			var toURL = this.href;
			var mode =  $(this).hasClass('go_to_create') ? 'create' : 'browse';
			atto.layout.switchBrowseAndCreate(fromURL, toURL, mode);
		});
		
		$('a.not_ready').click(function(ev){
			atto.message.show('서비스 준비중입니다.');
		});
		
		// 메시지
		atto.message.init();
		
		// Top 버튼 추가 (팝업 아닌 경우에만)
		if ($('#header, #container, #footer').length==3) {
			if (!$('#container').hasClass('main')) {
				atto.layout.appendBtnTop();
			}
		}
	});
})(window);

