/**
 * @fileoverview
 * cafenMap v21 레인맵의 각종 함수입니다.
 * 당 프로그램의 저작권은 http://cafen.net (outmind@nate.com)에 있습니다
 * 당 프로그램의 수정 후 재 배포는 저작권자의 허락을 득한 후 재배포 할수 있습니다. 
 * 당 프로그램의 이용은 비 상업적인 목적의 경우 무료로 이용할 수 있습니다.
 * 당 프로그램의 이용은 상업적인 목적의 경우 저작권자의 허락을 득한 후 이용할 수 있습니다.
 * 당 프로그램의 설치후 관리자는 outmind@nate.com 으로 설치하였다는 통보 메일을 발송하여야 합니다.
 * 당 프로그램안에 있는 모든 저작권 표시 영역은 수정할수 없습니다.
 *
 * ------------------------------------------------
 * 설치 방법은 함께 배포된 README 파일 참조 바랍니다.
 * ------------------------------------------------
 *
 * @author Kimjonggab(outmind@nate.com)
 * @copyright Copyright (c) 2004 Cafen.net (http://cafen.net)
 */


if (typeof csList == 'undefined') {
	if (cafen.srartLoad)
		cafen.srartLoad(_cafen_service_url+'images/map/lib/rainMapUtil.js');
	else
		document.write('<scr'+'ipt TYPE="text/JavaScript" charset="utf-8" LANGUAGE="JavaScript1.2" SRC="'+_cafen_service_url+'images/map/lib/rainMapUtil.js"></scr'+'ipt>');
}


function cafenMap() {}

cafenMap.prototype = {
	render : function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = arguments[i];
			if (typeof element == 'string')
				element = document.getElementById(element);
			if (element != null)
				this._renderElement(element);
		}
	},
	renderElements : function(renderObjs) {
		for(var i=0; i < renderObjs.length; i++) 
			this.renderElement(renderObjs[i]);
	},
	renderElement : function() {
		for (var i = 0; i < arguments.length; i++) {
			var element = arguments[i];
			if (typeof element == 'string')
				element = document.getElementById(element);
			if (element != null)
				this._renderElement(element);
		}
	},
	_renderElement : function(mapObj) {
		if (typeof mapObj.parse != 'undefined')
			return ;
		var tmpObj = null;
		var isEditable = false;
		if (mapObj.tagName == 'TEXTAREA' || mapObj.tagName == 'INPUT') {
			var tagValue = mapObj.value;
			var tmpObj = document.createElement("DIV");
			tmpObj.setAttribute('width', mapObj.getAttribute('width') || mapObj.offsetWidth);
			tmpObj.setAttribute('height', mapObj.getAttribute('height') || mapObj.offsetHeight);
			var copyAttrib = ['apitype','useanimate','toolbar','skin','keyword','lat', 'lon','zoom','maptype','toolbaroff'];
			for(var i = 0 ; i <  copyAttrib.length ; i++) {
				var attKey = 	copyAttrib[i];
				var attVal = mapObj.getAttribute(attKey) || '';
				if (attVal != null && attVal != '') 
					tmpObj.setAttribute(attKey, attVal);
			}
			tagValue = tagValue.replace(/<mark/gi, '<span');
			tagValue = tagValue.replace(/ type=/gi, ' marktype=');
			tagValue = tagValue.replace(/<\/mark>/gi, '</span>');
			tagValue = tagValue.replace(/<map/gi, '<div');
			tagValue = tagValue.replace(/<\/map>/gi, '</div>');
			tmpObj.innerHTML = tagValue;
			isEditable = true;
		} else {
			tmpObj = 	mapObj;
			isEditable = false;
		}
		var iseditable = mapObj.getAttribute('iseditable');
		if (iseditable != null)
			isEditable = (iseditable.toLowerCase() != 'false') ? true : false;
		var textAttribObj = new cafen.Attribute(tmpObj);
		var childNodes = textAttribObj.getChildNodes();
		var userMark = [];
		var mapInfo = {}
		for(var i =0; i < childNodes.length; i++) {
			var markNode = childNodes[i];
			if (markNode.nodeName == 'MARK' || markNode.nodeName == 'SPAN') {
				var lat = markNode.getFloat('lat',37.553965);
				var lon = markNode.getFloat('lon',126.9728);
				var label = markNode.get('label','');
				var markType = markNode.getInt('type',-1);
				if (markType == -1)
					markType = markNode.getInt('marktype',1);
				var markIcon = markNode.getInt('icon',1);
				var markColor = markNode.getInt('txtcolor',0);
				var urltxt = markNode.get('urltxt','');
				var urltype = markNode.getInt('urltype',0);
				var extra = markNode.get('extra','');
				var extratype = markNode.get('extratype','');
				userMark.push([lat,lon,markType, label, markIcon, markColor, isEditable, extra, extratype,urltxt,urltype]);
			} else if (markNode.nodeName == 'MAP' || markNode.nodeName == 'DIV') {
				mapInfo = {
					width : markNode.getInt('width',null),
					height : markNode.getInt('height',null), 
					APIType : markNode.get('apitype','auto'),
					toolbar : markNode.get('toolbar',null),
					toolbaroff : markNode.getBoolean('toolbaroff',false),
					skin : markNode.get('skin','base'),
					useanimate : markNode.getBoolean('useanimate',true),
					Keyword: markNode.get('keyword',''), 
					Lat : markNode.getFloat('lat',37.553965), 
					Lon : markNode.getFloat('lon',126.9728), 
					Zoom : markNode.getInt('zoom',10), 
					MapType : markNode.getInt('maptype','0')
				}
			}
		}
		var mapOptions = {
			width : textAttribObj.getInt('width',mapInfo.width || mapObj.offsetWidth),
			height : textAttribObj.getInt('height',mapInfo.height || mapObj.offsetHeight), 
			APIType : textAttribObj.get('apitype',mapInfo.APIType || 'auto'),
			toolbar : textAttribObj.get('toolbar',mapInfo.toolbar || null),
			toolbaroff : textAttribObj.getBoolean('toolbaroff', mapInfo.toolbaroff || false),
			useAnimate : textAttribObj.getBoolean('useanimate', mapInfo.useanimate || true),
			skin : textAttribObj.get('skin',mapInfo.skin || 'base'),
			Keyword: textAttribObj.get('keyword', mapInfo.Keyword || ''), 
			Lat : textAttribObj.getFloat('lat', mapInfo.Lat || 37.553965), 
			Lon : textAttribObj.getFloat('lon',mapInfo.Lon || 126.9728), 
			Zoom : textAttribObj.getInt('zoom',mapInfo.Zoom || 10), 
			MapType : textAttribObj.getInt('maptype',mapInfo.MapType || '0'),
			userMark : userMark, 
			hideMenu : !textAttribObj.getBoolean('showmenu',true), 
			isEditable : isEditable, 
			showInfo : '', 
			isTransparent : false
		}
		new cafen.RMap(mapObj, mapOptions);
	},
	/**
	* render Elements by className
	* @param {string}  className The class name of the Object to do render
	*/
	renderElementsByClassName : function(className) {
		var objs = cafen.getElementsByTagNames(['div','textarea','input']);
		var mapObjs = [];
		for(var i =0; i < objs.length; i++) {
			var child = objs[i];
			if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) 
				mapObjs.push(child);
		}
		for(var i=0; i < mapObjs.length; i++) 
			this.renderElement(mapObjs[i]);
	},
	/**
	* render Elements by id
	* @param {string}  id The id of the Object to do render
	*/
	renderElementsById : function(id) {
		if (document.getElementById(id) != null) {
			var mapObjs = [];
			var objs = document.getElementsByTagName(document.getElementById(id).tagName);
			for(var i=0;i<objs.length;i++){
				if(objs[i].id==id) 
					mapObjs.push(objs[i]);
			}
			for(var i=0; i < mapObjs.length; i++) 
				this.renderElement(mapObjs[i]);
		}
	},
	/**
	* render Elements by className
	* @param {string}  className The class name of the Object to do render
	*/
	renderElementsByName : function(objName) {
		var objs = cafen.getElementsByTagNames(['textarea','input']);
		var mapObjs = [];
		for(var i =0; i < objs.length; i++) {
			var child = objs[i];
			if (child.getAttribute('name') == objName) 
				mapObjs.push(child);
		}
		for(var i=0; i < mapObjs.length; i++) 
			this.renderElement(mapObjs[i]);
	}
}


/**
 * @class 지도첨부
 * @constructor 
 * @param {object} id 대상 Object
 */
cafen.RMap = function(id, options) {
	this.initRMap(id, options);	
};

cafen.RMap.prototype = {
	base_img_url : 'http://service.cafen.net/images/map/',
	base_xml_url : 'http://map.cafen.net/xml_map.html',
	baseIconCnt : 61,
	topHeight : 22,
	baseIconSize : {width : 26, height : 37},
	baseIconCoord : {left : -12, top : -27},
	basePolyline : {color : '#008000', weight : 5, markIcon : 0},
	searchAPI : {},
	mapObj : null,
	overlayObj : [],
	boundsObj : {top : null, left : null, bottom : null, right : null},
	version : 'M21',
	_mapObject : {},
	_loadedMap : {},
	keyMapShortCut : {
		'zoomin' : 'I',
		'zoomout' : 'O',
		'moveleft' : 'H',
		'moveup' : 'U',
		'movedown' : 'J',
		'moveright' : 'K'
	},
	initRMap : function(id, options) {
		cafen.getMonitor(this.version);
		this.options = cafen.extend({skin: 'base',toolbar : 'base', width : null, height : null , APIType : 'auto',Keyword: '', Lat : 37.553965, Lon : 126.9728, Zoom : 7, MapType : 0, userMark : [], hideMenu : false, showInfo : '', isTransparent : false, defaultColor : '#000000', useAnimate : true, toolbaroff : false}, options);
		this.options.classConf = (cafen.RMap.Conf.skin[this.options.skin] != null) ? cafen.RMap.Conf.skin[this.options.skin] : cafen.RMap.Conf.skin['base'];
		this.linkObj = cafen.$(id);
		this._loadedMap = {};
		this._mapObject = {};
		this.mapObj = null;
		
		if (this.options.width == null)
			this.options.width = parseInt((this.linkObj.offsetWidth) ? this.linkObj.offsetWidth : this.linkObj.style.width);
		if (!this.options.width)
			this.options.width = 700;
		if (this.options.width < 300)
			this.options.width = 300;
		if (this.options.width > 1500)
			this.options.width = 1500;
		if (this.options.height == null)
			this.options.height = parseInt((this.linkObj.offsetHeight) ? this.linkObj.offsetHeight : this.obj.style.height);
		if (!this.options.width)
			this.options.height = 700;
		if (this.options.height < 100)
			this.options.height = 100;
		if (this.options.height > 1500)
			this.options.height = 1500;
		if (this.linkObj.tagName == 'TEXTAREA' || this.linkObj.tagName == 'INPUT') {
			this.orgObj = this.linkObj;
			this.linkObj = document.createElement("DIV");
			this.linkObj.className = 'r_div';
			try {
				this.orgObj.parentNode.insertBefore(this.linkObj, this.orgObj);
			} catch(ex) {
				this.orgObj.insertAdjacentElement("beforeBegin",this.linkObj)
			}
			cafen.hide(this.orgObj);
		} else {
			this.linkObj.className = 'r_div';
			this.orgObj = this.linkObj;
		}
		cafen.setStyle(this.linkObj, {width:'auto', height:'auto'});
		this._mapObject.frmSkin = new cafen.TableAuto({className : this.getClassName('box'), attribute : {border : 0}, style : {width :(this.options.width -6) +'px', height : 'auto'}});
		this.linkObj.appendChild(this._mapObject.frmSkin.getObject());
		this._mapObject.mapPopup = new cafen.XWindow({style :{zIndex : '5000000'}});
		this.linkObj.appendChild(this._mapObject.mapPopup.getObject());
		this._mapObject.toogleSatus = true;
		this._mapObject.withInSearch = false;
		this._mapObject.buttonAreaOut = new cafen.TableAuto({className : this.getClassName('buttonarea'), align:'left', attribute : {border:0},style : {width:(this.options.width-12) +'px', display : (this.options.toolbaroff) ? 'none' : ''}});
		this._mapObject.buttonArea = new cafen.Div({align:'left', style : {width:(this.options.width -29)+'px', overflowX : 'hidden'}});
		this._mapObject.buttonAreaOut.addCell(this._mapObject.buttonArea);
		this._mapObject.buttonAreaOut.addStyle({width: (this.options.width -29) +'px'});
		this._mapObject.buttonToggle = new cafen.XIcon({icon:'r_winset', off :60, on : 14,  over :45, style:{width: '15px', height: '14px'}, event:{click : this.toggleToolBar.bind(this)}})
		this._mapObject.buttonAreaOut.addCell(this._mapObject.buttonToggle);
		this._mapObject.buttonAreaOut.addStyle({width:'17px', verticalAlign: 'bottom', textAlign:'right'});
		this._mapObject.frmSkin.addRow(this._mapObject.buttonAreaOut);
		this.drawToolbar();
		this._mapObject.mapArea = new cafen.Div({style:{width: (this.options.width -6) + 'px', height : 'auto', position:'relative', textAlign:'left', marginTop: (this.options.toolbaroff) ? '0px'  : '3px'}});
		this._mapObject.frmSkin.addRow(this._mapObject.mapArea);
		this.base_img_url = cafen.RMap.Conf.img_url;
		this.base_xml_url = cafen.RMap.Conf.xml_url;
		this.baseIconCnt = cafen.RMap.Conf.baseIconCnt;
		this.searchAPI = cafen.RMap.Conf.searchAPI;
		var maptype = this.options.APIType;
		this.changeAPI(maptype);
		if (this.mapObj != null) {
			this.orgObj.move = this.setPanning.bind(this);
			this.orgObj.zoom = this.setZooming.bind(this);
			this.orgObj.center = this.setCenter.bind(this);
			this.orgObj.view = this.setMapType.bind(this);
			this.orgObj.keyword = this.moveByKeyword.bind(this);
			this.orgObj.end = this.getMapInfo.bind(this);
			this.orgObj.getMapObject = this.getMapObject.bind(this);
			this.orgObj.getTags = this.getMapTags.bind(this);
			this.orgObj.parse = this.end.bind(this);
		}  
	},
	end : function() {
		if (this.orgObj.tagName == 'INPUT' || this.orgObj.tagName == 'TEXTAREA') 
			this.orgObj.value = this.getMapTags();
		return true;
	},
	getMapTags : function() {
		var mapInfo = this.getMapInfo(); 
		var mapTags = [];
		mapTags.push('<map')
		if (mapInfo.Lat != null && mapInfo.Lon != null)
			mapTags.push(' lat="'+mapInfo.Lat+'" lon="'+mapInfo.Lon+'" ');
		if (mapInfo.Zoom != null)
			mapTags.push(' zoom="'+mapInfo.Zoom+'" ');
		if (mapInfo.MapType != null )
			mapTags.push(' maptype="'+mapInfo.MapType+'" ');
		mapTags.push('></map>');
		for(var i = 0 ; i < mapInfo.userMark.length; i++) {
			mapTags.push('<MARK');
			var marker = mapInfo.userMark[i];
			if (marker[0] != null && marker[1] != null)
				mapTags.push(' lat="'+marker[0]+'" lon="'+marker[1]+'" ');
			if (marker[2] != null)
				mapTags.push(' type="'+marker[2]+'"  ');
			if (marker[3] != null)
				mapTags.push(' label="'+marker[3]+'"  ');
			if (marker[4] != null)
				mapTags.push(' icon="'+marker[4]+'"  ');
			if (marker[5] != null)
				mapTags.push(' txtcolor="'+marker[5]+'"  ');
			if (marker[7] != null)
				mapTags.push(' extra="'+marker[7]+'"  ');
			if (marker[8] != null)
				mapTags.push(' extratype="'+marker[8]+'"  ');
			if (marker[9] != null)
				mapTags.push(' urltxt="'+marker[9]+'"  ');
			if (marker[10] != null)
				mapTags.push(' urltype="'+marker[10]+'"  ');
			mapTags.push('></MARK>');
		}
		return mapTags.join('');
	},
	getClassName : function(part) {
		switch(part) {
			case 'tab' : 
				return this.options.classConf.class_Tab;
				break;
			case 'box' :
				return this.options.classConf.class_Box;
				break;
			case 'buttonarea' :
				return this.options.classConf.class_ButtonArea;
				break;
			case 'buttonbg' :
				return this.options.classConf.class_Button;
				break;
			default :
				return '';
				break;
		}
	},
	_menusetData : null,
	getMenuSet : function() {
		if (this._menusetData == null) 
			this._menusetData = cafen.extendMax(cafenMsg.getObject('map_menu'), cafenGlobalConf.mapToolbarSet);
		return this._menusetData;
	},
	drawToolbar : function() {
		var buttonInfo = cafenMsg.getObject('map_buttonInfo');
		var groupstart = false;
		var groupmiddle = false;
		var groupend = false;
		var groupAlign = 'left';
		var menuObj = this.getMenuSet();
		var toolbarSet = (menuObj[this.options.toolbar] != null) ? menuObj[this.options.toolbar] : menuObj.base;
		var cnt = toolbarSet.length;
		var currRowObj = null;
		this.statusButton = [];
		this.actionButton = {};
		var iconMargin = null;
		if(cafen.browser.isIE) 
			iconMargin = '0 0 0 3px';
		else if(cafen.browser.isFF) 
			iconMargin = '-1 0 0 0px';
		else
			iconMargin = '3px 0px 3px 2px';
		for(var i = 0; i < cnt ; i++) {
			if (currRowObj == null) {
				switch (groupAlign) {
					case 'center' :
					case 'right' :
						currRowObj = new cafen.TableAuto({attribute : {border:0, align: groupAlign},style : {}});
						var tmpAlignObj = new cafen.Div({style: {textAlign: groupAlign, height : '22px'}});
						tmpAlignObj.appendChild(currRowObj);
						this._mapObject.buttonArea.appendChild(tmpAlignObj);
						break;
					default :
						currRowObj = new cafen.TableAuto({attribute : {border:0},style : {}});
						this._mapObject.buttonArea.appendChild(currRowObj);
						break;
				}
				currRowObj.addRow();
			}
			var idx = toolbarSet[i];
			
			switch(idx) {
				case 'separator':
					break;
				case 'group' :
				case '[' :
					groupstart = true;
					groupmiddle = false;
					groupend = false;
					break;
				case 'break' :
				case ']' :
					groupstart = false;
					groupmiddle = false;
					groupend = false;
					currRowObj.addCell();
					currRowObj.addStyle({width:'3px'});
					currRowObj.addText('<div style="width:3px;font-size:1px;line-height:1px;display:block;overflow:hidden;">&nbsp;</div>');
					break;
				case 'blank' :
					currRowObj.addCell();
					currRowObj.addStyle({width:'3px'});
					currRowObj.addText('<div style="width:3px;font-size:1px;line-height:1px;display:block;overflow:hidden;">&nbsp;</div>');
					break;
				case 'linebreakc' :
				case 'linebreakl' :
				case 'linebreakr' :
				case 'linebreakb' :
				case 'linebreak' :
					groupstart = false;
					groupmiddle = false;
					groupend = false;
					switch(idx) {
						case 'linebreakr' :
							groupAlign = 'right';
							break;
						case 'linebreakc' :
							groupAlign = 'center';
							break;
						default :
							groupAlign = 'left';
							break;
					}
					if (idx == 'linebreak')
						this._mapObject.buttonArea.appendChild(new cafen.Div({style:{height:'3px', margin:'1px 6px 2px 6px', fontSize:'1px', backgroundPosition : '0 -1122px', backgroundRepeat : 'repeat-x'}, attribute : {className : this.getClassName('buttonbg')}}));
					else
						this._mapObject.buttonArea.appendChild(new cafen.Div({style:{height:'3px', margin:'0px', fontSize:'1px'}}));
					currRowObj = null;
					break;
				default :
					var currButton = buttonInfo[idx];
					var buttonNo = currButton[2];
					var x = (buttonNo % 10) * 16;
					var y = Math.floor(buttonNo /10) * 16;
					var icon = null;
					var bindCommand = null;
					switch(idx) {
						case 'polycolor':
							icon = new cafen.XImage({className :'r_mapset',x: x,y : y}, {style:{cssFloat : 'left',margin : iconMargin, width:'16px', height:'16px'},attribute :{unselectable : 'on'}, childNodes : [new cafen.RMap.ButtonColor()]});
							bindCommand = (currButton[0] != null) ? this.execCommand.bind(this,currButton[0],'','') : this.actionCommand.bind(this,idx,'','');
							break;
						case 'search' :
							icon = new cafen.TableAuto({style:{cssFloat : 'left',margin : '3px 5px 3px 3px', padding:'0',position :'relative'}});
							this._mapObject.inputSearch = new cafen.Input({shortkey : 'K',style:{width:'75px', height:'16px',fontSize:'11px',padding :'0px',margin:'0px'},attribute :{}, event :{end : this.searchKeyword.bind(this)}});
							icon.addCell(this._mapObject.inputSearch);
							icon.addCell(new cafen.Button({style:{width:'20px', height:'16px',padding:'0', overflow:'hidden'},attribute :{unselectable : 'on'}, event : {click : this.showSearchResult.bind(this)}}));
							break;
						case 'markicon' :
							icon = new cafen.XImage({className :'r_mapmark',x: 0,y : 0}, {style:{cssFloat : 'left',margin : iconMargin, width:'16px', height:'16px'},attribute :{unselectable : 'on'}});
							bindCommand = (currButton[0] != null) ? this.execCommand.bind(this,currButton[0],'','') : this.actionCommand.bind(this,idx,'','');
							break;
						default :
							icon = new cafen.XImage({className :'r_mapset',x: x,y : y}, {style:{cssFloat : 'left',margin : iconMargin, width:'16px', height:'16px'},attribute :{unselectable : 'on'}});
							bindCommand = (currButton[0] != null) ? this.execCommand.bind(this,currButton[0],'','') : this.actionCommand.bind(this,idx,'','');
							break;
					}
					var tmpButton = null;
					var baseBgPos = 0,baseSize =0 , basePadding = 0; 
					if (currButton[5] != null ) {
						if (currButton[5] > 60) {
							baseBgPos = 792;
							baseSize  = 100;
						} else if (currButton[5] > 30) {
							baseBgPos = 528;
							baseSize  = 56;
						} else {
							baseBgPos = 0;
							baseSize  = 33;
						}
						basePadding = 0;
					} else {
						baseBgPos = 264;
						baseSize  = 24;
						basePadding = 0;
					}
					if (icon != null) {
						var nextidx = (cnt -1 >= i +1) ? toolbarSet[i+1] : '';
						var tagButton = (bindCommand != null ) ? 'button' : 'div';
						var eventBind = (bindCommand == null ) ? {} : {click:bindCommand};
						if (!groupstart) {
							tmpButton = new cafen.XIcon({tag : tagButton, icon : this.getClassName('buttonbg'), off : baseBgPos+132, on : 22 , over : 100, style :{width:baseSize +'px', paddingRight:  basePadding + 'px'}, attribute :{unselectable : 'on'}, event :eventBind, childNodes : [icon]}) ;
							currRowObj.addCell(tmpButton);
							currRowObj.addStyle({width:baseSize +'px'});
							currRowObj.addCell();
							currRowObj.addStyle({width:'3px'});
							currRowObj.addText('<div style="width:3px;font-size:1px;line-height:1px;display:block;overflow:hidden;">&nbsp;</div>');
						} else {
							if (nextidx == 'group' || nextidx == 'break' || nextidx == ']'  || nextidx == ']' || nextidx == 'linebreak' || nextidx == 'linebreakb')
								groupend = true;
							var title = currButton[1];
							var shortkey = null;
							if (this.keyMapShortCut[idx] != null) {
								shortkey = this.keyMapShortCut[idx];
								title += ' ('+this.keyMapShortCut[idx]+')'
							}
							if (!groupmiddle && groupend) {
								tmpButton = new cafen.XIcon({tag : tagButton, shortkey : shortkey, icon : this.getClassName('buttonbg'), off : baseBgPos+198, on : 22 , over : 100, style :{width:baseSize +'px', paddingRight:  basePadding + 'px'}, attribute :{unselectable : 'on', title : title}, event :eventBind, childNodes : [icon]}) ;
								currRowObj.addCell(tmpButton);
								currRowObj.addStyle({width:baseSize +'px'});
							} else if (!groupmiddle) {
								tmpButton = new cafen.XIcon({tag : tagButton, shortkey : shortkey, icon : this.getClassName('buttonbg'), off : baseBgPos, on : 22 , over : 100, style :{width:baseSize +'px', paddingRight:  basePadding + 'px'}, attribute :{unselectable : 'on', title : title}, event :eventBind, childNodes : [icon]}) ;
								currRowObj.addCell(tmpButton);
								currRowObj.addStyle({width:baseSize +'px'});
							} else if (groupend) {
								tmpButton = new cafen.XIcon({tag : tagButton, shortkey : shortkey, icon : this.getClassName('buttonbg'), off : baseBgPos+132, on : 22 , over : 100, style :{width:baseSize +'px', paddingRight:  basePadding + 'px'}, attribute :{unselectable : 'on', title : title}, event :eventBind, childNodes : [icon]}) ;
								currRowObj.addCell(tmpButton);
								currRowObj.addStyle({width:baseSize +'px'});
							} else {
								tmpButton = new cafen.XIcon({tag : tagButton, shortkey : shortkey, icon : this.getClassName('buttonbg'), off : baseBgPos+66, on : 22 , over : 100, style :{width:baseSize +'px', paddingRight:  basePadding + 'px'}, attribute :{unselectable : 'on', title : title}, event :eventBind, childNodes : [icon]}) ;
								currRowObj.addCell(tmpButton);
								currRowObj.addStyle({width:baseSize +'px'});
							}
							this.actionButton[idx] = {classObj : null, obj : tmpButton};
							if (currButton[4])
								this.statusButton.push({cmd : idx, obj : tmpButton});
							groupmiddle = true;
						}
					}
					break;
			}
		}				
	},
	showMsg : function(msg, pos) {
		msg = '<div style="padding:10px 5px 10px 5px;">'+msg+'</div>';
		if (this._mapObject.alert == null) {
			this._mapObject.alert = new cafen.XAlert({title :cafenMsg.get('com_alert'), contents :'', sticker : {obj : this._mapObject.frmSkin, x : 'center', y : 'middle'}, style : {width: '300px'}});
			this._mapObject.alert.setContents(msg, null);
			this._mapObject.mapPopup.addChild(this._mapObject.alert);
		}
		this._mapObject.alert.setContents(msg, pos ? {y : 'exbottom', plus : [0, 20]} : {y : 'top', plus : [0, 40]});
		this._mapObject.alert.onLoad();
	},
	showContents : function(contents, contentstype) {
		if (this._mapObject.contentsViewer == null) 
			this._mapObject.contentsViewer = new cafen.RMap.contentsViewer(this);
		switch(contentstype) {
			case 'image' :
				this._mapObject.contentsViewer.setImage(contents);
				break;
			case 'movie' :
				this._mapObject.contentsViewer.setMovie(contents);
				break;
			case 'roadview' :
				this.setPanoId(contents);
				break;
			case 'map' :
				this._mapObject.contentsViewer.setMap(contents);
				break;
		}
	},
	_panoIdCallBack : null,
	showRoadView: function(lat, lon, callBack) {
		if (	this.roadViewClient == null) {
			if (typeof DRoadViewClient != 'undefined') {
				this.roadViewClient = new DRoadViewClient();
			} else {
				if (cafen.checkAPI('DMap')) {
					this.lastRoadViewPos = [lat, lon, callBack];
					cafen.RMap.Conf.loadAPI('DMap', this.reloadRoadView.bind(this));
				} else
					this.showMsg(cafenMsg.get('map_0042'));
				return false;
			}
		}
		if (	this.roadViewClient != null) {
			this._panoIdCallBack = callBack;
			this.roadViewClient.getNearestRoadView(new DLatLng(lat,  lon), this.getNearestRoadView.bind(this));
		}
	},
	reloadRoadView : function() {
		this.showRoadView(this.lastRoadViewPos[0],this.lastRoadViewPos[1], this.lastRoadViewPos[2]);
	},
	hideRoadView: function() {
	
	},
	getNearestRoadView : function(data) {
		if(data.service) {
			if (this._panoIdCallBack != null)
				this._panoIdCallBack(data.id);
			else
				this.setPanoId(data.id);
		} else
			this.showMsg(cafenMsg.get('map_0043'));
	},
	setPanoId : function(id) {
		if (this.roadView == null) {
			if (typeof DRoadView != 'undefined') {
				this.roadView = new cafen.RMap.roadView(this, {sticker : {obj : this._mapObject.frmSkin, x : 'center', y : 'middle'}, linkButton : this.actionButton['roadview'].obj});
			} else {
				if (cafen.checkAPI('DMap')) {
					this._lastPanoId = id;
					cafen.RMap.Conf.loadAPI('DMap', this.reloadPanoId.bind(this));
				} else
					this.showMsg(cafenMsg.get('map_0042'));
				return false;
			}
		}
		if (this.roadView != null) {
			this.roadView.onLoad();
			this.roadView.setValue(id);
		}
	},
	reloadPanoId : function() {
		this.setPanoId(this._lastPanoId);
	},
	searchKeyword : function(obj) {
		var keyword = (obj.getValue) ? obj.getValue() : obj;
		if (keyword.split(' ').join('') == '') {
			this.showMsg(cafenMsg.get('map_0005'));
			this._mapObject.inputSearch.focus();
		} else {
			if (cafen.checkAPI('GMap')) {
				if (this._mapObject.withInSearch) {
					var mapInfo = this.getCenter();
					var ll = mapInfo.Lat +','+mapInfo.Lon;
					var pos = this.getXYLatLon(0,0);
					var spn = (mapInfo.Lat - pos[1])+','+(pos[0] - mapInfo.Lon);
					var param = {
						q: keyword,
						ll : ll,
						spn :  spn,
						output : 'json',
						oe:'utf8',
						hl :'ko',
						sensor:'false',
						key: cafen.getAPI('GMap')
					};
				} else {
					var param = {
						q: keyword,
						output : 'json',
						oe:'utf8',
						hl :'ko',
						sensor:'false',
						key: cafen.getAPI('GMap')
					};
				}
				cafen.smallSWFAjax.getFlashXml(param,this.setkeywordResult.bind(this),'http://maps.google.com/maps/geo', true);	
			} else {
				this.showMsg(cafenMsg.get('map_0031'));
			}
		}
	},
	setkeywordResult : function(txt) {
		var json = cafen.getString2Json(txt);
		if (json.Status) {
			if (json.Status.code == 200 && json.Placemark)  {
				if (json.Placemark.length > 0) {
					this.removeAllMarker(0);
					var queryData = [];
					for(var i = 0; i< json.Placemark.length; i++) {
						var Lon = json.Placemark[i].Point.coordinates[0];
						var Lat = json.Placemark[i].Point.coordinates[1];
						var Address = json.Placemark[i].address.replace('\uB300\uD55C\uBBFC\uAD6D','');
						queryData.push({Lat : Lat, Lon : Lon, Address : Address});
						this.addMarker(Lat, Lon, Address , 0 , 700+i,0, true);
					}
					if (queryData.length > 0) {
						this.setCenter(queryData[0].Lat, queryData[0].Lon);
						this._mapObject.queryData = queryData;
						this._mapObject.queryKeyword = json.name;
						if (this._mapObject.searchResultOnEndShow) 
							this.showSearchResult();
					} else
						this.showMsg(cafenMsg.get('map_0009'));
				} else
					this.showMsg(cafenMsg.get('map_0009'));
			} else
				this.showMsg(cafenMsg.get('map_0009'));
		} else
			this.showMsg(cafenMsg.get('map_0009'));
		this._mapObject.searchResultOnEndShow = false;
	},
	showSearchResult : function() {
		if (this._mapObject.inputSearch.getValue() == '') {
			this.showMsg(cafenMsg.get('map_0005'));
			this._mapObject.inputSearch.focus();
		} else if (this._mapObject.queryKeyword != null && this._mapObject.queryKeyword == this._mapObject.inputSearch.getValue()) {
			if (this._mapObject.searchResultObj == null) {
				var cmd = 'search';
				this._mapObject.searchResultObj = new cafen.RMap.searchResult(
					this,
					{
						sticker : {obj : this.actionButton[cmd].obj, x : 'left', y : 'bottom'},
						linkButton : this.actionButton[cmd].obj,
						style : {}
					}
				);
				this._mapObject.mapPopup.addChild(this._mapObject.searchResultObj);
			}
			this._mapObject.searchResultObj.onLoad();
		}else {
			this.showMsg(cafenMsg.get('map_0008'));
			this.searchKeyword(this._mapObject.inputSearch);
			this._mapObject.searchResultOnEndShow = true;
		}
	},
	disableButton : function(cmd, bl) {
		for(var i = 0; i < this.statusButton.length; i++) {
			var obj = 	this.statusButton[i];
			if (obj.cmd.toLowerCase() == cmd)
				obj.obj.setDisable(bl);
		}
	},
	actionCommand : function(cmd,obj) {
		if (this._lastCommand == cmd)  {
			this._mapObject.mapPopup.closeChild();
			this._lastCommandObj = null;
			this._lastCommand = null;
		} else {		
			this._lastCommandObj = null;
			this._lastCommand = cmd;
			switch(cmd) {
				default : 
					this._lastCommandObj = this.getActionObject(cmd,obj);
					break;
			}
			if (this._lastCommandObj != null) 
				this._lastCommandObj.onLoad();
		}
	},
	getActionObject : function(cmd) {
		if (this.actionButton[cmd].classObj != null)
			return this.actionButton[cmd].classObj;
		else {
			switch(cmd) {
				case 'mapworld' :
				case 'mapkorea' :
					this.actionButton[cmd].classObj = new cafen.RMap.indexMap(
						this,
						cmd, 
						{
							sticker : {obj : this.actionButton[cmd].obj, x : 'left', y : 'bottom'},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				case 'showinfo' :
					this.actionButton[cmd].classObj = new cafen.RMap.showInfo(
						this,
						{
							sticker : {obj :  this._mapObject.mapArea, x : 'left', y : 'top', plus : [10, 10]},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				case 'pointweather' :
				case 'areaweather' :
					this.actionButton[cmd].classObj = new cafen.RMap.showWeather(
						this,
						{
							sticker : {obj :  this._mapObject.mapArea, x : 'left', y : 'top', plus : [10, 10]},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				case 'polycolor' :
					this.actionButton[cmd].classObj = new cafen.RMap.ColorPicker(
						this,
						'polycolor',
						{
							sticker : {obj : this.actionButton[cmd].obj, x : 'left', y : 'bottom'},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				case 'markicon' :
					this.actionButton[cmd].classObj = new cafen.RMap.markIcon(
						this,
						{
							sticker : {obj : this.actionButton[cmd].obj, x : 'left', y : 'bottom'},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				case 'pointinfo' :
				case 'areainfo' :
					this.actionButton[cmd].classObj = new cafen.RMap.areaInfo(
						this,
						{
							sticker : {obj :  this._mapObject.mapArea, x : 'center', y : 'top', plus : [10, 10]},
							linkButton : this.actionButton[cmd].obj,
							style : {}
						}
					);
					break;
				default :
					break;
			}
			if (this.actionButton[cmd].classObj != null)
				this._mapObject.mapPopup.addChild(this.actionButton[cmd].classObj);
			return this.actionButton[cmd].classObj;
		}
	},
	buttonUpdate : function() {
		for(var i = 0; i < this.statusButton.length; i++) {
			var obj = 	this.statusButton[i];
			switch(obj.cmd.toLowerCase()) {
				case 'mtmap' :
					obj.obj.setSelected((this.getMapType() == 0));
					break;
				case 'mtsat' :
					obj.obj.setSelected((this.getMapType() == 1));
					break;
				case 'mthyb' :
					obj.obj.setSelected((this.getMapType() == 2));
					break;
				case 'apinaver' :
					obj.obj.setSelected((this.options.APIType == 'NMap'));
					break;
				case 'apidaum' :
					obj.obj.setSelected((this.options.APIType == 'DMap'));
					break;
				case 'apiyahoo' :
					obj.obj.setSelected((this.options.APIType == 'YMap'));
					break;
				case 'apigoogle' :
					obj.obj.setSelected((this.options.APIType == 'GMap'));
					break;
				case 'apimsn' :
					obj.obj.setSelected((this.options.APIType == 'VEMap'));
					break;
			}
		}
	},
	execCommand : function(cmd, val) {
		this._mapObject.mapPopup.closeChild();
		this._lastCommandObj = null;
		this._lastCommand = null;
		switch(cmd.toLowerCase()) {
			case 'withinsearch' :
				this._mapObject.withInSearch = this.actionButton[cmd].obj.toggleSelect();
				break;
			case 'typemap' : 
				this.setMapType(0);
				break;
			case 'typesat' : 
				this.setMapType(1);
				break;
			case 'typehyb' : 
				this.setMapType(2, true);
				break;
			case 'zoomout' : 
				this.setZoom(null,1);
				break;
			case 'zoomin' : 
				this.setZoom(null,-1);
				break;
			case 'moveup' :
				this.setPanning(0);
				break;
			case 'movedown' :
				this.setPanning(2);
				break;
			case 'moveleft' :
				this.setPanning(3);
				break;
			case 'moveright' :
				this.setPanning(1);
				break;
			case 'apimsn' :
				this.changeAPI('VEMap');
				break;
			case 'apinaver' :
				this.changeAPI('NMap');
				break;
			case 'apiyahoo' :
				this.changeAPI('YMap');
				break;
			case 'apigoogle' :
				this.changeAPI('GMap');
				break;
			case 'apidaum' :
				this.changeAPI('DMap');
				break;
			case 'pointinfo' :
			case 'roadview' :
			case 'pointweather' :
			case 'poly' :
			case 'user' :
				this.getPoint(cmd.toLowerCase());
				break;
			case 'deletepoly' :
				this.removeAllMarker(2,0);
				break;
			case 'togglepoly' :
				this._mapObject.togglePoly = this.actionButton['polytoggle'].obj.toggleSelect();
				if (this._mapObject.togglePoly) {
					this.removeAllMarker(2,1);
					this.disableButton('polydel', true);
					this.disableButton('poly', true);
				} else {
					this.removeAllMarker(2,2);
					this.disableButton('polydel', false);
					this.disableButton('poly', false);
				}
			case 'polycolor' :
				this.basePolyline.color = val;
				this.actionButton['polycolor'].obj.childNodes[0].childNodes[0].setColor(val);
				this.mapObj.drawPolyline()
				break;
			case 'deleteuser' :
				this.getMarkObject().setDeleteEvent(true);
				this.removeAllMarker(1,0);
				break;
			case 'delete' :
				this.getPoint(cmd.toLowerCase());
				break;
			case 'toggleuser' :
				this._mapObject.togglePoly = this.actionButton['usertoggle'].obj.toggleSelect();
				if (this._mapObject.togglePoly) {
					this.removeAllMarker(1,1);
					this.disableButton('userdel', true);
					this.disableButton('user', true);
				} else {
					this.removeAllMarker(1,2);
					this.disableButton('userdel', false);
					this.disableButton('user', false);
				}
				break;
			case 'deletefind' :
				this.removeAllMarker(0,0);
				break;
			case 'togglefind' :
				this._mapObject.toggleFind = this.actionButton['findtoggle'].obj.toggleSelect();
				if (this._mapObject.toggleFind) {
					this.removeAllMarker(0,1);
					this.disableButton('finddel', true);
				} else {
					this.removeAllMarker(0,2);
					this.disableButton('finddel', false);
				}
				break;
			case 'markicon' :
				this.basePolyline.markIcon = val;
				var x = (val % 10) * 16;
				var y = Math.floor(val /10) * 16;
				this.actionButton['markicon'].obj.childNodes[0].setIcon(null, x,y);
				this.mapObj.drawPolyline()
				break;
			default :
				break;
		}
		this.buttonUpdate();
	},
	toggleToolBar : function() {
		this._mapObject.buttonToggle.isSelected = !this._mapObject.buttonToggle.isSelected;
		this._mapObject.buttonToggle.setSelected(this._mapObject.buttonToggle.isSelected);
		if (!this._mapObject.buttonToggle.isSelected) {
			this._mapObject.buttonArea.show();
			this._mapObject.toogleSatus = true;
		} else {
			this._mapObject.buttonArea.hide();
			this._mapObject.toogleSatus = false;
		}
		this.mapObj.reSize();
	},
	getMapObject : function(){
		return this;
	},
	changeAPI : function(maptype) {
		if (maptype == 'auto') {
			if (typeof YMap != 'undefined') 
				maptype = 'YMap';
			else if (typeof GMap2 != 'undefined') 
				maptype = 'GMap';
			else if (typeof NMap != 'undefined') 
				maptype = 'NMap';
			else if (typeof DMap != 'undefined') 
				maptype = 'DMap';
			else if (typeof VEMap != 'undefined') 
				maptype = 'VEMap';
			else
				maptype = '';
		}
		this.disableButton('apigoogle', (typeof GMap2 == 'undefined'));
		this.disableButton('apiyahoo', (typeof YMap == 'undefined'));
		this.disableButton('apinaver', (typeof NMap == 'undefined'));
		var oldMapInfo = null;
		if (this.mapObj != null) {
			oldMapInfo = this.getMapInfo();
			this.mapObj.hide();
		}
		if (this._loadedMap[maptype] != null) {
			this.options.APIType = maptype;
			this.mapObj = this._loadedMap[maptype];
			this.mapObj.show();
		} else {
			var newMap = null;
			var nullMapType = '';
			if ((maptype == 'YMap' && typeof YMap == 'undefined') || (maptype == 'GMap' && typeof GMap2 == 'undefined') || 	(maptype == 'NMap' && typeof NMap == 'undefined')  || 	(maptype == 'DMap' && typeof DMap == 'undefined') || (maptype == 'VEMap' && typeof VEMap == 'undefined')) {
				nullMapType = maptype;
				maptype = '';
			}
			switch(maptype) {
				case 'YMap' :
					this.options.APIType = 'YMap';
					newMap = new cafen.RMap.YMap(this);
					break;
				case 'NMap' :
					this.options.APIType = 'NMap';
					newMap = new cafen.RMap.NMap(this);
					break;
				case 'GMap' :
					this.options.APIType = 'GMap';
					newMap = new cafen.RMap.GMap(this);
					break;
				case 'DMap' :
					this.options.APIType = 'DMap';
					newMap = new cafen.RMap.DMap(this);
					break;
				case 'VEMap' :
					this.options.APIType = 'VEMap';
					newMap = new cafen.RMap.VEMap(this);
					break;
				default :
					this.options.APIType = 'NullMap';
					newMap = new cafen.RMap.NullMap(this, nullMapType);
					break;
			}
			this._loadedMap[maptype] = newMap;
			this.mapObj  = newMap;
		}
		this.setMapInfo(oldMapInfo);
	},
/**
 * Overlay 추가하기
 * @param {object} overlay
 */
	addOverlay : function(overlay) {
		this.overlayObj.push(overlay);
	},
/**
 * Overlay 제거하기
 * @param {object} overlay
 */
	removeOverlay : function(overlay) {
		var newOverlay = [];
		for(var i = 0; i < this.overlayObj.length; i++) {
			var obj =  this.overlayObj[i];
			if (overlay != obj)
				newOverlay.push(obj);
		}
		this.overlayObj = newOverlay;
	},
/**
 * Overlay 다시 그리기
 */
	reDraw : function() {
		for(var i = 0 ; i < this.overlayObj.length; i++) {
			this.overlayObj[i].reDraw();
		}
	},
/**
 * 키워드 설정
 * @param {string} 키워드
 */
	moveByKeyword :function(keyword) {
		if (keyword != '') {
			if (this._mapObject.inputSearch != null) 
				this._mapObject.inputSearch.setValue(keyword);
			this.searchKeyword(keyword);		
		}
	},
/**
 * 메세지 가져오기
 * @param {string} 메세지
 * @param {string} 기본값
 * @param {function} 리턴 함수
 * @param {number} 높이
 */
	getPrompt : function(msg, default_value, return_fnc, height) {
		if (height == null)
			height = 17;
		var popup_class = this.getPopupClass();
		popup_class.add(new cafen.Popup.prompt(msg, this.setPrompt.bind(this),{value:default_value, height : height}, this.style_class), {is_scrollable:true});
		this.lastPrompt_fnc = return_fnc;
	},
/**
 * 메세지 설정하기
 * @param {string} 메세지
 */
	setPrompt : function(msg) {
		this.lastPrompt_fnc(msg);
	},
/**
 * 지도 확대/축소하기
 * @param {boolean} 확대/축소여부
 */
	setZooming :function(zoom) {
		this.mapObj.setZoom(null, (zoom) ? -1 : 1);
	},
/**
 * 한국 지도내 위치 여부
 * @param {number} 위도
 * @param {number} 경도
 * @return {boolean} 포함여부
 */
	isInKorea :function(lat, lon) {
		return (lat < 40.0 && lat > 33.0 && lon > 120.0 && lon < 140.0) ;
	},
/**
 * 지도 이동하기
 * @param {boolean} 확대/축소여부
 */
	setZooming :function(zoom) {
		this.setZoom(null, (zoom) ? -1 : 1);
	},
/**
 * 지도 이동하기
 * @param {int} 이동 방향
 */
	setPanning :function(dir) {
		switch(dir) {
			case 0 :
				var pos = this.getXYLatLon(this.getWidth()/2 ,this.getHeight()/4);
				this.setCenter(pos[0],pos[1],true);
				break;
			case 2 :
				var pos = this.getXYLatLon(this.getWidth()/2 ,this.getHeight()/4*3);
				this.setCenter(pos[0],pos[1],true);
				break;
			case 3 :
				var pos = this.getXYLatLon(this.getWidth()/4 ,this.getHeight()/2);
				this.setCenter(pos[0],pos[1],true);
				break;
			case 1 :
				var pos = this.getXYLatLon(this.getWidth()/4*3 ,this.getHeight()/2);
				this.setCenter(pos[0],pos[1],true);
				break;
		}
	},
	latLngToPixel : function(lat, lng, zoom) {
 		var centerPoint=Math.pow(2,zoom+7),
 			totalPixels=centerPoint*2,
 			pixelsPerLngDegree=totalPixels/360,
 			pixelsPerLngRadian=totalPixels/(2*Math.PI),
 			siny=Math.min(Math.max(Math.sin(lat*(Math.PI/180)),-0.9999),0.9999);
 		return{
 			x:Math.round(centerPoint+lng*pixelsPerLngDegree),
 			y:Math.round(centerPoint-0.5*Math.log((1+siny)/(1-siny))*pixelsPerLngRadian)
 		}
	},
	pixelToLatLng : function(x, y, zoom) { 
 		var centerPoint=Math.pow(2,zoom+7),
 			totalPixels=centerPoint*2,
 			pixelsPerLngDegree=totalPixels/360,
 			pixelsPerLngRadian=totalPixels/(2*Math.PI);
		return {
			lat : (2*Math.atan(Math.exp(-(y-centerPoint)/pixelsPerLngRadian))-Math.PI/2) /(Math.PI/180), 
			lon : (x-centerPoint)/pixelsPerLngDegree
		};
	},
	getMouseObject : function() {
		if (this._mapObject.mouseObj == null)
			this._mapObject.mouseObj = new cafen.RMap.Mouse(this);
		return this._mapObject.mouseObj;
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 * @param {string} msg 메세지
 * @param {function} stopEvent 종료 이벤트
 */
	setEvent : function(clickEvent, msg, stopEvent, cmd) {
		if (typeof clickEvent == 'function') {
			this.getMouseObject().setEvent(clickEvent, (typeof msg == 'undefined') ? cafenMsg.get('map_0001') : msg, stopEvent, cmd);
		} else
			this.getMouseObject().unsetEvent();
	},
	getPoint : function(cmd, options) {
		this.lastCmd = cmd;
		if (this.onStopPointBind == null)
			this.onStopPointBind = this.onStopPoint.bind(this);
		var msg = null;
		switch(cmd.toLowerCase()) {
			case 'addmarker' :
				this.lastPointInfo = options;
				msg = cafenMsg.get('map_0006');
				break;
			case 'pointweather'	:
				msg = cafenMsg.get('map_0034');
				break;
			case 'roadview' :
				msg = cafenMsg.get('map_0041');
				break;
			case 'poly'	:
				msg = cafenMsg.get('map_0007');
				break;
			case 'user'	:
				msg = cafenMsg.get('map_0006');
				break;
			case 'delete'	:
				msg = cafenMsg.get('map_0040');
				break;
			default :
				msg = cafenMsg.get('map_0021');
				break;
		}
		this.setEvent(this.setPoint.bind(this), msg, this.onStopPointBind, cmd);
	},
	setPoint : function(lat, lon) {
		switch(this.lastCmd) {
			case 'addmarker' :
				this.addMarker(lat,lon,this.lastPointInfo.label, 1, this.basePolyline.markIcon, 0, true, '', '', this.lastPointInfo.urlTxt, this.lastPointInfo.urlType);
				this.setEvent(null);
				break;
			case 'pointweather' :
				var obj = this.getActionObject('pointweather');
				obj.setLatLon(lat, lon);
				obj.onLoad();
				this.setEvent(null);
				break;
			case 'pointinfo' :
				var obj = this.getActionObject('pointinfo');
				obj.setLatLon(lat, lon);
				obj.onLoad();
				this.setEvent(null);
				break;
			case 'roadview' :
				this.showRoadView(lat, lon);
				this.setEvent(null);
				break;
			case 'delete' :
				break;
			case 'poly' :
				this.addMarker(lat, lon, '', 2, this.basePolyline.markIcon ,0, true);
				break;
			case 'user' :
				this.addMarker(lat, lon, '', 1, this.basePolyline.markIcon ,0, true);
				break;
			default :
				alert(this.lastCmd);
				break;
		}
	},
	onStopPoint : function() {
		
	},
/**
 * 프로세싱 메세지 설정
 * @param {string} msg 메세지
 */
	setProcess : function(msg) {
		this.mouseObj.setMsg(msg);
	},
/**
 * 오브젝트 폭 가져오기
 * @return {int} 폭
 */
	getWidth : function() {
		return this.options.width - 6;
	},
/**
 * 오브젝트 높이 가져오기
 * @return {int} 높이
 */
	getHeight : function() {
		return this.options.height;
	},
/**
 * 위도 가져오기
 * @return {float} 위도
 */
	getLatitude : function() {
		return this.options.Lat;
	},
/**
 * 경도 가져오기
 * @return {float} 경도
 */
	getLongitude : function() {
		return this.options.Lon;
	},
	getXYLatLon : function(x,y) {
		return this.mapObj.getXYLatLon(x,y);
	},
	getLatLonXY : function(lat, lon) {
		return this.mapObj.getLatLonXY(lat, lon);
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {int} markType 마크 타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {boolean} isEditable 편집가능여부
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (extra == null)
			extra = '';
		if (extratype == null)
			extratype = '';
		if (urlTxt == null)
			urlTxt = '';
		if (urlType == null)
			urlType = '';
		this.mapObj.addMarker(lat,lon, label, markType, markIcon, markColor,isEditable, extra, extratype, urlTxt, urlType);
	},
/**
 * 마크 삭제하기/숨기기 보이기
 * @param {int} markType 대상 마크 타잎
 * @param {int} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		this.hideMarker();
		this.mapObj.removeAllMarker(markType, markHidden);
	},
	removeMarker : function(marker) {
		this.mapObj.removeMarker(marker);
	},
	modifyMarker : function(id, options) {
		this.mapObj.modifyMarker(id, options);
	},
	getMarkObject : function() {
		if (this.markObj == null)
			this.markObj = new cafen.RMap.RMarker(this);
		return this.markObj;
	},
	reSynkMarker : function(id) {
		var markerObj = this.mapObj.markers[id];
		this.mapObj.showMarker(markerObj.obj);
	},
	showMarker : function(seqn, lat, lon, label, marktype, icon, color, isEditable,extra, extraType, urlTxt, urlType) {
		this.getMarkObject().setObj(seqn, lat, lon, label, marktype, icon, color, isEditable,extra, extraType, urlTxt, urlType);
		this.getMarkObject().show();
	},
	getMarkerInfo : function(idx) {
		return this.mapObj.getMarkerInfo(idx);
	},
	hideMarker : function() {
		this.getMarkObject().hide();
	},
	setPaning : function(bl) {
		this.mapObj.setPaning(bl);
	},
	setBounds : function(top, left, bottom, right) {
		var x = (right - left) * 0.5;
		var y = (top - bottom) * 0.5;
		this.boundsObj = {top : top + y  , left:left - x, bottom : bottom - y, right : right + x};
	},
	isInBounds : function(lat, lon) {
		if (this.boundsObj.top > lat && this.boundsObj.bottom < lat && this.boundsObj.left < lon && this.boundsObj.right > lon) 
			return true;
		else
			return false;
	},
/**
 * 줌레벨 가져오기
 * @return {int} 줌레벨
 */
	getZoom : function() {
		return this.options.Zoom;
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		this.mapObj.setZoom(level, move);
	},
/**
 * 키워드설정
 * @param {string} mapType 맵타잎
 */
	setKeyword : function(keyword) {
		this.options.Keyword = keyword;
	},
/**
 * 맵타잎가져오기
 * @return {int} mapType 맵타잎
 */
	getMapType : function() {
		return this.options.MapType;
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 * @param {boolean} rotateType 맵타잎로테이션
 */
	setMapType : function(mapType, rotateType) {
		this.options.MapType = mapType;
		this.mapObj.setMapType(mapType,rotateType);
	},
/**
 * 맵정보 가져오기
 * @return  {array} 설정된 맵정보
 */
	getMapInfo : function(options) {
		options = cafen.extend({0 : true, 1:true, 2:true, 3 : true}, options);
		var markers =  this.mapObj.getMarker(options);
		var mapinfo = cafen.extend(this.options, this.mapObj.getMapInfo());
		mapinfo.userMark = markers;
		return mapinfo;
	},
/**
 * 맵정보 설정하기
 * @param  {object} 맵정보
 */
	setMapInfo : function(mapinfo) {
		this.options = cafen.extend(this.options, mapinfo);
		var oldMapInfo = {Lat : null, Lon : null}
		try {
			oldMapInfo = this.getCenter();
		} catch(ex) {}
		if (oldMapInfo.Lat != this.options.Lat || oldMapInfo.Lon != this.options.Lon)
			this.setCenter(this.options.Lat, this.options.Lon);
		if (oldMapInfo.Zoom != this.options.Zoom)
			this.setZoom(this.options.Zoom);
		if (oldMapInfo.MapType != this.options.MapType)
			this.setMapType(this.options.MapType);
		this.disableButton('mapworld', !this.mapObj.mapFunc.world);
		this.disableButton('mtsat', !this.mapObj.mapFunc.sat);
		this.disableButton('mthyb', !this.mapObj.mapFunc.hyb);
		this.buttonUpdate();
		if (this._mapObject.toolSize == null || isNaN(this._mapObject.toolSize)) 
			this._mapObject.toolSize = this._mapObject.buttonAreaOut.getObjectSize()[1]+2;
		if (!isNaN(this._mapObject.toolSize))
			this.mapObj.reSize();
		this.removeAllMarker(0, 0);
		this.removeAllMarker(1, 0);
		this.removeAllMarker(2, 0);
		this.removeAllMarker(3, 0);
		var markEditable = (this.options.isEditable) ? true : null;
		for(var i =0; i < this.options.userMark.length ; i++) {
			var marker = this.options.userMark[i];
			if (typeof marker[0] == 'number' && typeof marker[1] == 'number')  
				this.addMarker(marker[0],marker[1],(typeof marker[3] == 'undefined') ? '' : marker[3], (typeof marker[2] == 'undefined') ? 0 : marker[2], (typeof marker[4] == 'undefined') ? 0 : marker[4], (typeof marker[5] == 'undefined') ? 0 : marker[5] , (typeof marker[6] == 'undefined') ? markEditable || false : markEditable || marker[6], (typeof marker[7] == 'undefined') ? '' : marker[7], (typeof marker[8] == 'undefined') ? '' : marker[8], (typeof marker[9] == 'undefined') ? '' : marker[9], (typeof marker[10] == 'undefined') ? '' : marker[10]);
		}
	},
/**
 * 비활성화시 실행
 */
	onClose : function() {
		this.setEvent();
	},
/**
 * 중심 정보 가져오기
 * @return {object} 맵정보
 */
	getCenter : function() {
		return this.mapObj.getMapInfo();
	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		this.options.Lat = lat;
		this.options.Lon = lon;
		this.mapObj.setCenter(lat,lon,pan);
	},
	setAjax : function(data, callback) {
		if (this.AjaxObj == null)
			this.AjaxObj = new cafen.RMap.Ajax(this);
		this.AjaxObj.setAjax(data, callback);
	},
	getCoordinatesCS : function(cstype) {
		if (this.TM128_naver == null || this.KOREA_center == null  || this.WGS84_google== null) {
			this.TM128_naver = new CS(csList.TM128_katech_3param);
			this.WGS84_google = new CS(csList.GOOGLE_WGS84);
			this.KOREA_center = new CS(csList.KOREA_CENTER_TM_3param);
		}
		switch(cstype) {
			case 'KOREA_CENTER' : 
				return this.KOREA_center;
				break;
			case 'TM128' : 
				return this.TM128_naver;
				break;
			default : 
				return this.WGS84_google;
				break;
		}
	},
	getConvPositionType : function(x,y, CoordinatesType, convType) {
		if (typeof convType == 'undefined' || convType == '')
			convType = 'WGS';
		if (typeof CoordinatesType == 'undefined' || CoordinatesType == 'undefined')
			CoordinatesType = 'WGS';
		if (convType != CoordinatesType) {
			var orginal_cs = this.getCoordinatesCS(CoordinatesType);
			var target_cs = this.getCoordinatesCS(convType);
			switch(CoordinatesType) {
				case 'KOREA_CENTER' :
					var p = new PT(x/100, y/100);
					break;
				case 'TM128' :
					var p = new PT(x, y);
					break;
				default :
					var p = new PT(x, y);
					break;
			}
			cs_transform(orginal_cs,target_cs, p);
			return [p.x, p.y];
		} else
			return [x, y];
	},
	getExtraPolyline : function(extra, convType, step) {
		var lineinfo = extra.split(':');
		var linecolor =  (typeof lineinfo[0] != 'undefined' && lineinfo[0] != '') ? lineinfo[0] : '#ff0000';
		var linetype =  (typeof lineinfo[1] != 'undefined' && lineinfo[1] != '') ? lineinfo[1] : 'WGS';
		var lineposstr =  (typeof lineinfo[2] != 'undefined' && lineinfo[2] != '') ? lineinfo[2] : '';
		var lineposarr = lineposstr.split(',');
		var linepos = [];
		var i = 0;
		var show_rate =  (lineposarr.length > 100) ? step * 2 : 2;
		while(i < (lineposarr.length -1)) {
			if (lineposarr[i] != '' && lineposarr[i+1] != '') 
				linepos.push(this.getConvPositionType(parseFloat(lineposarr[i]) , parseFloat(lineposarr[i+1]),linetype, convType));
			i += show_rate ;
		}
		return {color : linecolor, lines : linepos, weight : 5};
	},
/**
 * 마크 이미지 가져오기
 * @param {int} 마크 번호
 * @return {string} 마크 이미지 URL
 */
	getMarkerImg : function(seqn, markType, extra_url, max_width) {
		if (markType == 3 && extra_url != '')
			return cafen.RMap.Conf.img_thumburl + extra_url + '_M' + max_width + '.jpg';
		else
			return this.base_img_url +'ico_'+seqn+'.png';
	},
/**
 * 오브젝트 가져오기
 * @param {object} 연결 오브젝트
 */
	getObject : function() {
		return this._mapObject.mapArea;
	},
	getTopObject : function() {
		return this.top_obj;	
	},
	getIconsetLength : function() {
		return this.baseIconCnt;
	}
}

/**
 * @class 지도 환경 정보
 */
cafen.RMap.Conf = {
	img_url : _cafen_service_url +'images/map/',
	img_popurl : _cafen_service_url + 'images/',
	img_thumburl : 'http://map.cafen.net/thumb/',
	xml_url : 'http://map.cafen.net/xml_map.html',
	default_search : 'GOOGLE',
	baseIconCnt : 61,	
	searchAPI : cafenMsg.getObject('map_api'),
	buttonColor : {
		bg : '#f1f1f1',
		bgline : '#d9d9d9',
		bgfont : '#464646',
		line : '#a0a0a0',
		off : '#e9ece9',
		on : '#d7d6d0',
		over : '#ffe8dc',
		disable : '#efeee7',
		btnwidth : 20,
		btnheight : 22
	},
	skin : {
		base : {
			class_Tab : 'r_tab', class_Box : 'r_btnskin', class_ButtonArea : 'r_boxblue', class_Editor : 'r_boxwhite', class_Button : 'r_wordset'
		},
		black : {
			class_Tab : 'r_tabblack', class_Box : 'r_boxblack', class_ButtonArea : 'r_boxblack', class_Editor : 'r_boxblack', class_Button : 'r_wordset_gray'
		},
		white : {
			class_Tab : 'r_tabwhite', class_Box : 'r_boxwhite', class_ButtonArea : 'r_boxgray', class_Editor : 'r_boxwhite', class_Button : 'r_wordset_gray'
		},
		silver : {
			class_Tab : 'r_tabgray', class_Box : 'r_boxgray', class_ButtonArea : 'r_boxgray', class_Editor : 'r_boxgray', class_Button : 'r_wordset_gray'
		},
		whitenblack : {
			class_Tab : 'r_tabblack', class_Box : 'r_boxblack', class_ButtonArea : 'r_boxgray', class_Editor : 'r_boxwhite', class_Button : 'r_wordset_gray'
		},
		blue : {
			class_Tab : 'r_tabgreen', class_Box : 'r_boxgreen', class_ButtonArea : 'r_boxgreen', class_Editor : 'r_boxgray', class_Button : 'r_wordset_green'
		},
		green : {
			class_Tab : 'r_tabgreen', class_Box : 'r_boxgreen', class_ButtonArea : 'r_boxgreen', class_Editor : 'r_boxgray', class_Button : 'r_wordset_green'
		},
		red : {
			class_Tab : 'r_tab_r', class_Box : 'r_boxred', class_ButtonArea : 'r_boxred', class_Editor : 'r_boxgray', class_Button : 'r_wordset_red'
		}		
	},
	colorSet : [
		{font : '#464646', border : '#909090', bg : '#ffffff'},
		{font : '#464646', border : '#7b7859', bg : '#f4eeaf'},
		{font : '#464646', border : '#805b5f', bg : '#feb3be'},
		{font : '#464646', border : '#806172', bg : '#f1b7d8'},
		{font : '#464646', border : '#427480', bg : '#78d2e6'},
		{font : '#464646', border : '#598077', bg : '#a2e7d7'},
		{font : '#464646', border : '#4d4943', bg : '#a9a196'},
		{font : '#464646', border : '#6a7e80', bg : '#b9dde0'},
		{font : '#464646', border : '#807377', bg : '#edd5dd'},
		{font : '#464646', border : '#807f7c', bg : '#efeee7'}
	],
	worldCitySet : [
		["Afghanistan, Kabul", +34.5833333333, +69.2],
		["Algeria, Algiers", +36.7666666667, +30.05],
		["Argentina, Buenos Aires", -34.5833333333, -58.4833333333],
		["Argentina, Cordoba", -31.3666666667, -64.25],
		["Argentina, Tucuman", -26.8333333333, -65.1666666667],
		["Australia, Adelaide", -34.9333333333, +138.583333333],
		["Australia, Alice Springs", -23.8, +133.883333333],
		["Australia, Brisbane", -27.4666666667, +153.033333333],
		["Australia, Darwin", -12.4666666667, +130.85],
		["Australia, Melbourne", -37.8166666667, +144.966666667],
		["Australia, Perth", -31.95, +115.85],
		["Australia, Sydney", -33.8666666667, +151.2],
		["Austria, Vienna", +48.25, +16.3666666667],
		["Azores, Lajes (Terceira)", +38.75, -27.0833333333],
		["Bahamas, Nassau", +25.0833333333, -77.35],
		["Bangladesh, Chittagong", +22.35, +91.8333333333],
		["Belgium, Brussels", +50.8, +4.35],
		["Bermuda, Kindley AFB", +33.3666666667, -64.6833333333],
		["Bolivia, La Paz", -16.5, -68.15],
		["Brazil, Belem", -1.45, -48.4833333333],
		["Brazil, Belo Horizonte", -19.9333333333, -43.95],
		["Brazil, Brasilia", -15.8666666667, -47.9166666667],
		["Brazil, Curitiba", -25.4166666667, -49.2833333333],
		["Brazil, Fortaleza", -3.76666666667, -38.55],
		["Brazil, Porto Alegre", -30.0333333333, -51.2166666667],
		["Brazil, Recife", -8.06666666667, -34.8833333333],
		["Brazil, Rio De Janeiro", -22.9166666667, -43.2],
		["Brazil, Salvador", -13, -38.5],
		["Brazil, Sao Paulo", -23.55, -46.6333333333],
		["Belize, Belize", +17.5166666667, -88.1833333333],
		["Bulgaria, Sofia", +42.7, +23.3333333333],
		["Burma, Mandalay", +21.9833333333, +96.1],
		["Burma, Rangoon", +16.7833333333, +96.15],
		["Cambodia, Phnom Penh", +11.55, +104.85],
		["Chile, Punta Arenas", -53.1666666667, -70.9],
		["Chile, Santiago", -33.45, -70.7],
		["Chile, Valparaiso", -33.0166666667, -71.6333333333],
		["China, Chongquing", +29.55, +106.55],
		["China, Shanghai", +31.2, +121.433333333],
		["Colombia, Baranquilla", +10.9833333333, -74.8],
		["Colombia, Bogota", +4.6, -74.0833333333],
		["Colombia, Cali", +3.41666666667, -76.5],
		["Colombia, Medellin", +6.21666666667, -75.6],
		["Congo, Brazzaville", -4.25, +15.25],
		["Cuba, Guantanamo Bay", +19.9, -75.15],
		["Cuba, Havana", +23.1333333333, -82.35],
		["Czechoslovakia, Prague", +50.0833333333, +14.4166666667],
		["Denmark, Copenhagen", +55.6833333333, +12.55],
		["Dominican republic, Santo Domingo", +18.4833333333, -69.9],
		["Equador, Guayaquil", -21, -79.8833333333],
		["Equador, Quito", -0.216666666667, -78.5333333333],
		["Egypt, Cairo", +29.8666666667, +31.3333333333],
		["El salvador, San Salvador", +13.7, -89.2166666667],
		["Ethiopia, Addis Ababa", +90.0333333333, +38.75],
		["Ethiopia, Asmara", +15.2833333333, +38.9166666667],
		["Finland, Helsinki", +60.1666666667, +24.95],
		["France, Lyon", +45.7, +4.78333333333],
		["France, Marseilles", +43.3, +5.38333333333],
		["France, Nantes", +47.25, -1.56666666667],
		["France, Nice", +43.7, +7.26666666667],
		["France, Paris", +48.8166666667, +2.48333333333],
		["France, Strasbourg", +48.5833333333, +7.76666666667],
		["French guiana, Cayenne", +4.93333333333, -52.45],
		["Germany, Berlin (West)", +52.45, +13.3],
		["Germany, Hamburg", +53.55, +9.96666666667],
		["Germany, Hannover", +52.4, +9.66666666667],
		["Germany, Mannheim", +49.5666666667, +8.46666666667],
		["Germany, Munich", +48.15, +11.5666666667],
		["Ghana, Accra", +5.55, -0.2],
		["Gibraltar, Gibraltar", +36.15, -5.36666666667],
		["Greece, Athens", +37.9666666667, +23.7166666667],
		["Greece, Thessaloniki", +40.6166666667, +22.95],
		["Greenland, Narsarssuaq", +61.1833333333, -45.4166666667],
		["Guatemala, Guatemala City", +14.6166666667, -90.5166666667],
		["Guyana, Georgetown", +6.83333333333, -58.2],
		["Haiti, Port Au Prince", +18.55, -72.3333333333],
		["Honduras, Tegucigalpa", +14.1, -87.2166666667],
		["Hong kong, Hong Kong", +22.3, +114.166666667],
		["Hungary, Budapest", +47.5166666667, +19.0333333333],
		["Iceland, Reykjavik", +64.1333333333, +21.9333333333],
		["India, Ahmenabad", +23.0333333333, +72.5833333333],
		["India, Bangalore", +12.95, +77.6166666667],
		["India, Bombay", +18.9, +72.8166666667],
		["India, Calcutta", +22.5333333333, +88.3333333333],
		["India, Madras", +13.0666666667, +80.25],
		["India, Nagpur", +21.15, +79.1166666667],
		["India, New Delhi", +28.5833333333, +77.2],
		["Indonesia, Djakarta", -6.18333333333, +106.833333333],
		["Indonesia, Kupang", -10.1666666667, +123.566666667],
		["Indonesia, Makassar", -5.13333333333, +119.466666667],
		["Indonesia, Medan", +3.58333333333, +98.6833333333],
		["Indonesia, Palembang", -3, +104.766666667],
		["Indonesia, Surabaya", -7.21666666667, +112.716666667],
		["Iran, Abadan", +30.35, +48.2666666667],
		["Iran, Meshed", +36.2833333333, +59.6],
		["Iran, Tehran", +35.6833333333, +51.4166666667],
		["Iraq, Baghdad", +33.3333333333, +44.4],
		["Iraq, Mosul", +36.3166666667, +43.15],
		["Ireland, Dublin", +53.3666666667, -6.35],
		["Ireland, Shannon", +52.6833333333, -8.91666666667],
		["Irian barat, Manokwari", -0.866666666667, +134.083333333],
		["Israel, Jerusalem", +31.7833333333, +35.2166666667],
		["Israel, Tel Aviv", +32.1, +34.7833333333],
		["Italy, Milan", +45.45, +9.28333333333],
		["Italy, Naples", +40.8833333333, +14.3],
		["Italy, Rome", +41.8, +12.6],
		["Ivory coast, Abidjan", +5.31666666667, -4.01666666667],
		["Japan, Fukuoka", +33.5833333333, +130.45],
		["Japan, Sapporo", +43.0666666667, +141.35],
		["Japan, Tokyo", +35.6833333333, +139.766666667],
		["Jordan, Amman", +31.95, +35.95],
		["Kenya, Nairobi", -1.26666666667, +36.8],
		["Korea, Pyongyang", +39.0333333333, +125.683333333],
		["Korea, Seoul", +37.5666666667, +126.966666667],
		["Lebanon, Beirut", +33.9, +35.4666666667],
		["Liberia, Monrovia", +6.3, -10.8],
		["Libya, Benghazi", +32.1, +20.0666666667],
		["Madagascar, Tananarive", -18.9166666667, +47.55],
		["Malaysia, Kuala Lumpur", +3.11666666667, +101.7],
		["Malaysia, Penang", +5.41666666667, +100.316666667],
		["Martinique, Fort De France", +14.6166666667, -61.0833333333],
		["Mexico, Guadalajara", +20.6833333333, -103.333333333],
		["Mexico, Merida", +20.9666666667, -89.6333333333],
		["Mexico, Mexico City", +19.4, -99.2],
		["Mexico, Monterrey", +25.6666666667, -100.3],
		["Mexico, Vera Cruz", +19.2, -96.1333333333],
		["Morocco, Casablanca", +33.5833333333, -7.65],
		["Nepal, Katmandu", +27.7, +85.2],
		["Netherlands, Amsterdam", +52.3833333333, +4.91666666667],
		["New zealand, Auckland", -36.85, +174.766666667],
		["New zealand, Christchurch", -43.5333333333, +172.616666667],
		["New zealand, Wellington", -41.2833333333, +174.766666667],
		["Nicaragua, Managua", +12.1666666667, -86.25],
		["Nigeria, Lagos", +6.45, +3.4],
		["Norway, Bergen", +60.4, +5.31666666667],
		["Norway, Oslo", +59.9333333333, +10.7333333333],
		["Pakistan, Karachi", +24.8, +66.9833333333],
		["Pakistan, Lahore", +31.5833333333, +74.3333333333],
		["Pakistan, Peshwar", +34.0166666667, +71.5833333333],
		["Panama, Panama City", +8.96666666667, -79.55],
		["Papua new guinea, Port Moresby", -9.48333333333, +147.15],
		["Paraguay, Ascuncion", -25.2833333333, -57.5],
		["Peru, Lima", -12.0833333333, -77.05],
		["Philippines, Manila", +14.5833333333, +120.983333333],
		["Poland, Krakow", +50.0666666667, +19.95],
		["Poland, Warsaw", +52.2166666667, +21.0333333333],
		["Portugal, Lisbon", +38.7166666667, -9.13333333333],
		["Puerto rico, San Juan", +18.4833333333, -66.1166666667],
		["Rumania, Bucharest", +44.4166666667, +26.1],
		["Russia, Alma Ata", +43.2333333333, +76.8833333333],
		["Russia, Archangel", +64.55, +40.5333333333],
		["Russia, Kaliningrad", +54.7166666667, +20.5],
		["Russia, Krasnoyarsk", +56.0166666667, +92.95],
		["Russia, Kiev", +50.45, +30.5],
		["Russia, Kharkov", +50, +36.2333333333],
		["Russia, Kuibyshev", +53.1833333333, +50.1],
		["Russia, Leningrad", +59.9333333333, +30.2666666667],
		["Russia, Minsk", +53.9, +27.55],
		["Russia, Moscow", +55.7666666667, +37.6666666667],
		["Russia, Odessa", +46.4833333333, +30.7333333333],
		["Russia, Petropavlovsk", +52.8833333333, +158.7],
		["Russia, Rostov on Don", +47.2166666667, +39.7166666667],
		["Russia, Sverdlovsk", +56.8166666667, +60.6333333333],
		["Russia, Tashkent", +41.3333333333, +69.3],
		["Russia, Tbilisi", +41.7166666667, +44.8],
		["Russia, Vladivostok", +43.1166666667, +131.916666667],
		["Russia, Volgograd", +48.7, +44.5166666667],
		["Saudi arabia, Dhahran", +26.2833333333, +50.15],
		["Saudi arabia, Jedda", +21.4666666667, +39.1666666667],
		["Saudi arabia, Riyadh", +24.65, +46.7],
		["Senegal, Dakar", +14.7, -17.4833333333],
		["Singapore, Singapore", +1.3, +103.833333333],
		["Somalia, Mogadiscio", +2.03333333333, +49.3166666667],
		["South africa, Cape Town", -33.9333333333, +18.4833333333],
		["South africa, Johannesburg", -26.1833333333, +28.05],
		["South africa, Pretoria", -25.75, +28.2333333333],
		["South yemen, Aden", +12.8333333333, +45.0333333333],
		["Spain, Barcelona", +41.4, +2.15],
		["Spain, Madrid", +40.4166666667, -3.68333333333],
		["Spain, Valencia", +39.4666666667, -0.383333333333],
		["Sri lanka, Colombo", +6.9, +79.8666666667],
		["Sudan, Khartoum", +15.6166666667, +32.55],
		["Surinam, Paramaribo", +5.81666666667, -55.15],
		["Sweden, Stockholm", +59.35, +18.0666666667],
		["Switzerland, Zurich", +47.3833333333, +8.55],
		["Syria, Damascus", +33.5, +36.3333333333],
		["Taiwan, Tainan", +22.95, +120.2],
		["Taiwan, Taipei", +25.0333333333, +121.516666667],
		["Tanzania, Dar es Salaam", -6.83333333333, +39.3],
		["Thailand, Bangkok", +13.7333333333, +100.5],
		["Trinidad, Port of Spain", +10.6666666667, -61.5166666667],
		["Tunisia, Tunis", +36.7833333333, +10.2],
		["Turkey, Adana", +36.9833333333, +35.3],
		["Turkey, Ankara", +39.95, +32.8833333333],
		["Turkey, Istanbul", +40.9666666667, +28.8333333333],
		["Turkey, Izmir", +38.4333333333, +27.1666666667],
		["United kingdom, Belfast", +54.6, -5.91666666667],
		["United kingdom, Birmingham", +52.4833333333, -1.93333333333],
		["United kingdom, Cardiff", +51.4666666667, -3.16666666667],
		["United kingdom, Edinburgh", +55.9166666667, -3.18333333333],
		["United kingdom, Glasgow", +55.8666666667, -4.28333333333],
		["United kingdom, London", +51.4833333333, -0],
		["Uruguay, Montevideo", -34.85, -56.2166666667],
		["US, Alabama, Alexander City", +32.95, -85.95],
		["US, Alabama, Anniston AP", +33.5833333333, -85.85],
		["US, Alabama, Auburn", +32.6, -85.5],
		["US, Alabama, Birmingham AP", +33.5666666667, -86.75],
		["US, Alabama, Decatur", +34.6166666667, -86.9833333333],
		["US, Alabama, Dothan AP", +31.3166666667, -85.45],
		["US, Alabama, Florence AP", +34.8, -87.6666666667],
		["US, Alabama, Gadsden", +34.0166666667, -86],
		["US, Alabama, Huntsville AP", +34.7, -86.5833333333],
		["US, Alabama, Mobile AP", +30.6833333333, -88.25],
		["US, Alabama, Mobile Co", +30.6666666667, -88.25],
		["US, Alabama, Montgomery AP", +32.3833333333, -86.3666666667],
		["US, Alabama, Selma-Craig AFB", +32.3333333333, -87.9833333333],
		["US, Alabama, Talladega", +33.45, -86.1],
		["US, Alabama, Tuscaloosa AP", +33.2166666667, -87.6166666667],
		["US, Alaska, Anchorage AP", +61.1666666667, -150.016666667],
		["US, Alaska, Barrow (S)", +71.3, -156.783333333],
		["US, Alaska, Fairbanks AP (S)", +64.8166666667, -147.866666667],
		["US, Alaska, Juneau AP", +58.3666666667, -134.583333333],
		["US, Alaska, Kodiak", +57.75, -152.483333333],
		["US, Alaska, Nome AP", +64.5, -165.433333333],
		["US, Arizona, Douglas AP", +31.45, -109.6],
		["US, Arizona, Flagstaff AP", +35.1333333333, -111.666666667],
		["US, Arizona, Fort Huachuca AP (S)", +31.5833333333, -110.333333333],
		["US, Arizona, Kingman AP", +35.2, -114.016666667],
		["US, Arizona, Nogales", +31.35, -110.916666667],
		["US, Arizona, Phoenix AP (S)", +33.4333333333, -112.016666667],
		["US, Arizona, Prescott AP", +34.65, -112.433333333],
		["US, Arizona, Tucson AP (S)", +32.1166666667, -110.933333333],
		["US, Arizona, Winslow AP", +35.0166666667, -110.733333333],
		["US, Arizona, Yuma AP", +32.65, -114.616666667],
		["US, Arkansas, Blytheville AFB", +35.95, -89.95],
		["US, Arkansas, Camden", +33.6, -92.8166666667],
		["US, Arkansas, El Dorado AP", +33.2166666667, -92.8166666667],
		["US, Arkansas, Fayetteville AP", +36, -94.1666666667],
		["US, Arkansas, Fort Smith AP", +35.3333333333, -94.3666666667],
		["US, Arkansas, Hot Springs", +34.4833333333, -93.1],
		["US, Arkansas, Jonesboro", +35.8333333333, -90.7],
		["US, Arkansas, Little Rock AP (S)", +34.7333333333, -92.2333333333],
		["US, Arkansas, Pine Bluff AP", +34.3, -92.0833333333],
		["US, Arkansas, Texarkana AP", +33.45, -93.9833333333],
		["US, California, Bakersfield AP", +35.4166666667, -119.05],
		["US, California, Barstow AP", +34.85, -116.783333333],
		["US, California, Blythe AP", +33.6166666667, -114.716666667],
		["US, California, Burbank AP", +34.2, -118.35],
		["US, California, Chico", +39.8, -121.85],
		["US, California, Concord", +37.9666666667, -121.983333333],
		["US, California, Covina", +34.0833333333, -117.866666667],
		["US, California, Crescent City AP", +41.7666666667, -124.2],
		["US, California, Downey", +33.9333333333, -118.133333333],
		["US, California, El Cajon", +32.8166666667, -116.966666667],
		["US, California, El Cerrito AP (S)", +32.8166666667, -115.666666667],
		["US, California, Escondido", +33.1166666667, -117.083333333],
		["US, California, Eureka/Arcata AP", +40.9833333333, -124.1],
		["US, California, Fairfield-Trafis AFB", +38.2666666667, -121.933333333],
		["US, California, Fresno AP (S)", +36.7666666667, -119.716666667],
		["US, California, Hamilton AFB", +38.0666666667, -122.5],
		["US, California, Laguna Beach", +33.55, -117.783333333],
		["US, California, Livermore", +37.7, -121.95],
		["US, California, Lompoc, Vandenberg AFB", +34.7166666667, -120.566666667],
		["US, California, Long Beach AP", +33.8166666667, -118.15],
		["US, California, Los Angeles AP (S)", +33.9333333333, -118.4],
		["US, California, Los Angeles CO (S)", +34.05, -118.233333333],
		["US, California, Merced-Castle AFB", +37.3833333333, -120.566666667],
		["US, California, Modesto", +37.65, -121],
		["US, California, Monterey", +36.6, -121.9],
		["US, California, Napa", +38.2166666667, -122.283333333],
		["US, California, Needles AP", +34.6, -114.616666667],
		["US, California, Oakland AP", +37.8166666667, -122.316666667],
		["US, California, Oceanside", +33.2333333333, -117.416666667],
		["US, California, Ontario", +34.05, -117.6],
		["US, California, Oxnard", +34.2, -119.183333333],
		["US, California, Palmdale AP", +34.6333333333, -118.1],
		["US, California, Palm Springs", +33.8166666667, -116.533333333],
		["US, California, Pasadena", +34.15, -118.15],
		["US, California, Petaluma", +38.2333333333, -122.633333333],
		["US, California, Pomona Co", +34.05, -117.75],
		["US, California, Redding AP", +40.5166666667, -122.3],
		["US, California, Redlands", +34.05, -117.183333333],
		["US, California, Richmond", +37.9333333333, -122.35],
		["US, California, Riverside-March AFB (S)", +33.9, -117.25],
		["US, California, Sacramento AP", +38.5166666667, -121.5],
		["US, California, Salinas AP", +36.6666666667, -121.6],
		["US, California, San Bernadino, Norton AFB", +34.1333333333, -117.266666667],
		["US, California, San Diego AP", +32.7333333333, -117.166666667],
		["US, California, San Fernando", +34.2833333333, -118.466666667],
		["US, California, San Francisco AP", +37.6166666667, -122.383333333],
		["US, California, San Francisco Co", +37.7666666667, -122.433333333],
		["US, California, San Jose AP", +37.3666666667, -121.933333333],
		["US, California, San Louis Obispo", +35.3333333333, -120.716666667],
		["US, California, Santa Ana AP", +33.75, -117.866666667],
		["US, California, Santa Barbara MAP", +34.4333333333, -119.833333333],
		["US, California, Santa Cruz", +36.9833333333, -122.016666667],
		["US, California, Santa Maria AP (S)", +34.9, -120.45],
		["US, California, Santa Monica CIC", +34.0166666667, -118.483333333],
		["US, California, Santa Paula", +34.35, -119.083333333],
		["US, California, Santa Rosa", +38.5166666667, -122.816666667],
		["US, California, Stockton AP", +37.9, -121.25],
		["US, California, Ukiah", +39.15, -123.2],
		["US, California, Visalia", +36.3333333333, -119.3],
		["US, California, Yreka", +41.7166666667, -122.633333333],
		["US, California, Yuba City", +39.1333333333, -121.6],
		["US, Colorado, Alamosa AP", +37.45, -105.866666667],
		["US, Colorado, Boulder", +40, -105.266666667],
		["US, Colorado, Colorado Springs AP", +38.8166666667, -104.716666667],
		["US, Colorado, Denver AP", +39.75, -104.866666667],
		["US, Colorado, Durango", +37.2833333333, -107.883333333],
		["US, Colorado, Fort Collins", +40.75, -105.083333333],
		["US, Colorado, Grand Junction AP (S)", +39.1166666667, -108.533333333],
		["US, Colorado, Greeley", +40.4333333333, -104.633333333],
		["US, Colorado, Lajunta AP", +38.05, -103.5],
		["US, Colorado, Leadville", +39.25, -106.3],
		["US, Colorado, Pueblo AP", +38.3, -104.483333333],
		["US, Colorado, Sterling", +40.6166666667, -103.2],
		["US, Colorado, Trinidad", +37.25, -104.333333333],
		["US, Connecticut, Bridgeport AP", +41.1833333333, -73.1833333333],
		["US, Connecticut, Hartford, Bcafenard Field", +41.7333333333, -72.65],
		["US, Connecticut, New Haven AP", +41.3166666667, -73.9166666667],
		["US, Connecticut, New London", +41.35, -72.1],
		["US, Connecticut, Norwalk", +41.1166666667, -73.4166666667],
		["US, Connecticut, Norwick", +41.5333333333, -72.0666666667],
		["US, Connecticut, Waterbury", +41.5833333333, -73.0666666667],
		["US, Connecticut, Widsor Locks, Bradley Fld", +41.9333333333, -72.6833333333],
		["US, Delaware, Dover AFB", +39.1333333333, -75.4666666667],
		["US, Delaware, Wilmington AP", +39.6666666667, -75.6],
		["US, District of columbia, Andrews AFB", +38.0833333333, -76.0833333333],
		["US, District of columbia, Washington, National AP", +38.85, -77.0333333333],
		["US, Florida, Belle Glade", +26.65, -80.65],
		["US, Florida, Cape Kennedy AP", +28.4833333333, -80.5666666667],
		["US, Florida, Daytona Beach AP", +29.1833333333, -81.05],
		["US, Florida, E Fort Lauderdale", +26.0666666667, -80.15],
		["US, Florida, Fort Myers AP", +26.5833333333, -81.8666666667],
		["US, Florida, Fort Pierce", +27.4666666667, -80.35],
		["US, Florida, Gainsville AP (S)", +29.6833333333, -82.2666666667],
		["US, Florida, Jacksonville AP", +30.5, -81.7],
		["US, Florida, Key West AP", +24.55, -81.75],
		["US, Florida, Lakeland Co (S)", +28.0333333333, -81.95],
		["US, Florida, Miami AP (S)", +25.8, -80.2666666667],
		["US, Florida, Miami Beach Co", +25.7833333333, -80.2833333333],
		["US, Florida, Ocala", +29.1833333333, -82.1333333333],
		["US, Florida, Orlando AP", +28.55, -81.3833333333],
		["US, Florida, Panama City, Tyndall AFB", +30.0666666667, -85.5833333333],
		["US, Florida, Pensacola Co", +30.4166666667, -87.2166666667],
		["US, Florida, St. Augustine", +29.9666666667, -81.3333333333],
		["US, Florida, St. Petersburg", +27.7666666667, -83.3333333333],
		["US, Florida, Stanford", +28.7666666667, -81.2833333333],
		["US, Florida, Sarasota", +27.3833333333, -82.55],
		["US, Florida, Tallahassee AP (S)", +30.3833333333, -84.3666666667],
		["US, Florida, Tampa AP (S)", +27.9666666667, -82.5333333333],
		["US, Florida, West Palm Beach AP", +26.6833333333, -80.1],
		["US, Georgia, Albany, Turner AFB", +31.6, -84.0833333333],
		["US, Georgia, Americus", +32.05, -84.2333333333],
		["US, Georgia, Athens", +33.95, -83.3166666667],
		["US, Georgia, Atlanta AP (S)", +33.65, -84.4333333333],
		["US, Georgia, Augusta AP", +33.3666666667, -81.9666666667],
		["US, Georgia, Brunswick", +31.25, -81.4833333333],
		["US, Georgia, Columbus, Lawson AFB", +32.5166666667, -84.9333333333],
		["US, Georgia, Dalton", +34.5666666667, -84.95],
		["US, Georgia, Dublin", +32.3333333333, -82.9],
		["US, Georgia, Gainsville", +34.1833333333, -83.6833333333],
		["US, Georgia, Griffin", +33.2166666667, -84.2666666667],
		["US, Georgia, LaGrange", +33.0166666667, -85.0666666667],
		["US, Georgia, Macon AP", +32.7, -83.65],
		["US, Georgia, Marietta, Dobbins AFB", +33.9166666667, -84.5166666667],
		["US, Georgia, Savannah", +32.1333333333, -81.2],
		["US, Georgia, Valdosta-Moody AFB", +30.9666666667, -83.2],
		["US, Georgia, Waycross", +31.25, -82.4],
		["US, Hawaii, Hilo AP (S)", +19.7166666667, -155.083333333],
		["US, Hawaii, Honolulu AP", +21.3333333333, -157.916666667],
		["US, Hawaii, Kaneohe Bay MCAS", +21.45, -157.766666667],
		["US, Hawaii, Wahiawa", +21.05, -158.033333333],
		["US, Idaho, Boise AP (S)", +43.5666666667, -116.216666667],
		["US, Idaho, Burley", +42.5333333333, -113.766666667],
		["US, Idaho, Coeur DAlene AP", +47.7666666667, -116.816666667],
		["US, Idaho, Idaho Falls AP", +43.5166666667, -112.066666667],
		["US, Idaho, Lewiston AP", +46.3833333333, -117.016666667],
		["US, Idaho, Moscow", +46.7333333333, -116.966666667],
		["US, Idaho, Mountain Home AFB", +43.0333333333, -115.9],
		["US, Idaho, Pocatello AP", +42.9166666667, -112.6],
		["US, Idaho, Twin Falls AP (S)", +42.4833333333, -114.483333333],
		["US, Illinois, Aurora", +41.75, -88.3333333333],
		["US, Illinois, Belleville, Scott AFB", +38.55, -89.85],
		["US, Illinois, Bloomington", +40.4833333333, -88.95],
		["US, Illinois, Carbondale", +37.7833333333, -89.25],
		["US, Illinois, Champaign/Urbana", +40.0333333333, -88.2833333333],
		["US, Illinois, Chicago, Midway AP", +41.7833333333, -87.75],
		["US, Illinois, Chicago, OHare AP", +41.9833333333, -87.9],
		["US, Illinois, Chicago Co", +41.8833333333, -87.6333333333],
		["US, Illinois, Danville", +40.2, -87.6],
		["US, Illinois, Decatur", +39.8333333333, -88.8666666667],
		["US, Illinois, Dixon", +41.8333333333, -89.4833333333],
		["US, Illinois, Elgin", +42.0333333333, -88.2666666667],
		["US, Illinois, Freeport", +42.3, -89.6166666667],
		["US, Illinois, Galesburg", +40.9333333333, -90.4333333333],
		["US, Illinois, Greenville", +38.8833333333, -89.4],
		["US, Illinois, Joliet", +41.5166666667, -88.1666666667],
		["US, Illinois, Kankakee", +41.0833333333, -87.9166666667],
		["US, Illinois, La Salle/Peru", +41.3166666667, -89.1],
		["US, Illinois, Macomb", +40.4666666667, -90.6666666667],
		["US, Illinois, Moline AP", +41.45, -90.5166666667],
		["US, Illinois, Mt Vernon", +38.3166666667, -88.8666666667],
		["US, Illinois, Peoria AP", +40.6666666667, -89.6833333333],
		["US, Illinois, Quincy AP", +39.95, -91.2],
		["US, Illinois, Rantoul, Chanute AFB", +40.3, -88.1333333333],
		["US, Illinois, Rockford", +42.35, -89.05],
		["US, Illinois, Springfield AP", +39.8333333333, -89.6666666667],
		["US, Illinois, Waukegan", +42.35, -87.8833333333],
		["US, Indiana, Anderson", +40.1, -85.6166666667],
		["US, Indiana, Bedford", +38.85, -86.5],
		["US, Indiana, Bloomington", +39.1333333333, -86.6166666667],
		["US, Indiana, Columbus, Bakalar AFB", +39.2666666667, -85.9],
		["US, Indiana, Crawfordsville", +40.05, -86.9],
		["US, Indiana, Evansville AP", +38.05, -87.5333333333],
		["US, Indiana, Fort Wayne AP", +41, -85.2],
		["US, Indiana, Goshen AP", +41.5333333333, -85.8],
		["US, Indiana, Hobart", +41.5333333333, -87.25],
		["US, Indiana, Huntington", +40.8833333333, -85.5],
		["US, Indiana, Indianapolis AP", +39.7333333333, -86.2833333333],
		["US, Indiana, Jeffersonville", +38.2833333333, -85.75],
		["US, Indiana, Kokomo", +40.4166666667, -86.05],
		["US, Indiana, Lafayette", +40.0333333333, -86.0833333333],
		["US, Indiana, La Porte", +41.6, -86.7166666667],
		["US, Indiana, Marion", +40.4833333333, -85.6833333333],
		["US, Indiana, Muncie", +40.1833333333, -85.35],
		["US, Indiana, Peru, Grissom AFB", +40.65, -86.15],
		["US, Indiana, Richmond AP", +39.7666666667, -84.8333333333],
		["US, Indiana, Shelbyville", +39.5166666667, -85.7833333333],
		["US, Indiana, South Bend AP", +41.7, -86.3166666667],
		["US, Indiana, Terre Haute AP", +39.45, -87.3],
		["US, Indiana, Valparaiso", +41.5166666667, -87.0333333333],
		["US, Indiana, Vincennes", +38.6833333333, -87.5333333333],
		["US, Iowa, Ames (S)", +42.0333333333, -93.8],
		["US, Iowa, Burlington AP", +40.7833333333, -91.1166666667],
		["US, Iowa, Cedar Rapids AP", +41.8833333333, -91.7],
		["US, Iowa, Clinton", +41.8333333333, -90.2166666667],
		["US, Iowa, Council Bluffs", +41.3333333333, -95.8166666667],
		["US, Iowa, Des Moines AP", +41.5333333333, -93.65],
		["US, Iowa, Dubuque", +42.4, -90.7],
		["US, Iowa, Fort Dodge", +42.55, -94.1833333333],
		["US, Iowa, Iowa City", +41.6333333333, -91.55],
		["US, Iowa, Keokuk", +40.4, -91.4],
		["US, Iowa, Marshalltown", +42.0666666667, -92.9333333333],
		["US, Iowa, Mason City AP", +43.15, -93.3333333333],
		["US, Iowa, Newton", +41.6833333333, -93.0333333333],
		["US, Iowa, Ottumwa AP", +41.1, -92.45],
		["US, Iowa, Sioux City AP", +42.4, -96.3833333333],
		["US, Iowa, Waterloo", +42.55, -92.4],
		["US, Kansas, Atchison", +39.5666666667, -95.1166666667],
		["US, Kansas, Chanute AP", +37.6666666667, -95.4833333333],
		["US, Kansas, Dodge City AP (S)", +37.7666666667, -99.9666666667],
		["US, Kansas, El Dorado", +37.8166666667, -96.8333333333],
		["US, Kansas, Emporia", +38.3333333333, -96.2],
		["US, Kansas, Garden City AP", +37.9333333333, -100.733333333],
		["US, Kansas, Goodland AP", +39.3666666667, -101.7],
		["US, Kansas, Great Bend", +38.35, -98.8666666667],
		["US, Kansas, Hutchinson AP", +38.0666666667, -97.8666666667],
		["US, Kansas, Liberal", +37.05, -100.966666667],
		["US, Kansas, Manhattan, Ft Riley (S)", +39.05, -96.7666666667],
		["US, Kansas, Parsons", +37.3333333333, -95.5166666667],
		["US, Kansas, Russell AP", +38.8666666667, -98.8166666667],
		["US, Kansas, Salina", +38.8, -97.65],
		["US, Kansas, Topeka AP", +39.0666666667, -95.6333333333],
		["US, Kansas, Wichita AP", +37.65, -97.4166666667],
		["US, Kentucky, Ashland", +38.55, -82.7333333333],
		["US, Kentucky, Bowling Green AP", +35.9666666667, -86.4666666667],
		["US, Kentucky, Corbin AP", +36.95, -84.1],
		["US, Kentucky, Covington AP", +39.05, -84.6666666667],
		["US, Kentucky, Hopkinsville, Ft Campbell", +36.6666666667, -87.4833333333],
		["US, Kentucky, Lexington AP (S)", +38.0333333333, -84.6],
		["US, Kentucky, Louisville AP", +38.1833333333, -85.7333333333],
		["US, Kentucky, Madisonville", +37.3166666667, -87.4833333333],
		["US, Kentucky, Owensboro", +37.75, -87.1666666667],
		["US, Kentucky, Paducah AP", +37.0666666667, -88.7666666667],
		["US, Louisiana, Alexandria AP", +31.4, -92.3],
		["US, Louisiana, Baton Rouge AP", +30.5333333333, -91.15],
		["US, Louisiana, Bogalusa", +30.7833333333, -89.8666666667],
		["US, Louisiana, Houma", +29.5166666667, -90.6666666667],
		["US, Louisiana, Lafayette AP", +30.2, -92],
		["US, Louisiana, Lake Charles AP (S)", +30.1166666667, -93.2166666667],
		["US, Louisiana, Minden", +32.6, -93.3],
		["US, Louisiana, Monroe AP", +32.5166666667, -92.0333333333],
		["US, Louisiana, Natchitoches", +31.7666666667, -93.0833333333],
		["US, Louisiana, New Orleans AP", +29.9833333333, -90.25],
		["US, Louisiana, Shreveport AP (S)", +32.4666666667, -93.8166666667],
		["US, Maine, Augusta AP", +44.3166666667, -69.8],
		["US, Maine, Bangor, Dow AFB", +44.8, -68.8333333333],
		["US, Maine, Caribou AP (S)", +46.8666666667, -68.0166666667],
		["US, Maine, Lewiston", +44.0333333333, -70.25],
		["US, Maine, Millinocket AP", +45.65, -68.7],
		["US, Maine, Portland (S)", +43.65, -70.3166666667],
		["US, Maine, Waterville", +44.5333333333, -69.6666666667],
		["US, Maryland, Baltimore AP", +39.1833333333, -76.6666666667],
		["US, Maryland, Baltimore Co", +39.3333333333, -76.4166666667],
		["US, Maryland, Cumberland", +39.6166666667, -78.7666666667],
		["US, Maryland, Frederick AP", +39.45, -77.4166666667],
		["US, Maryland, Hagerstown", +39.7, -77.7333333333],
		["US, Maryland, Salisbury (S)", +38.3333333333, -75.5],
		["US, Massachusetts, Boston AP", +42.3666666667, -71.0333333333],
		["US, Massachusetts, Clinton", +42.4, -71.6833333333],
		["US, Massachusetts, Fall River", +41.7166666667, -71.1333333333],
		["US, Massachusetts, Framingham", +42.2833333333, -71.4166666667],
		["US, Massachusetts, Gloucester", +42.5833333333, -70.6833333333],
		["US, Massachusetts, Greenfield", +42.05, -72.0666666667],
		["US, Massachusetts, Lawrence", +42.7, -71.1666666667],
		["US, Massachusetts, Lowell", +42.65, -71.3166666667],
		["US, Massachusetts, New Bedford", +41.6833333333, -70.9666666667],
		["US, Massachusetts, Pittsfield AP", +42.4333333333, -73.3],
		["US, Massachusetts, Springfield, Westover AFB", +42.2, -72.5333333333],
		["US, Massachusetts, Taunton", +41.9, -71.0666666667],
		["US, Massachusetts, Worcester AP", +42.2666666667, -71.8666666667],
		["US, Michigan, Adrian", +41.9166666667, -84.0166666667],
		["US, Michigan, Alpena AP", +45.0666666667, -83.4333333333],
		["US, Michigan, Battle Creek AP", +42.3166666667, -85.25],
		["US, Michigan, Benton Harbor AP", +42.1333333333, -86.4333333333],
		["US, Michigan, Detroit", +42.4166666667, -83.0166666667],
		["US, Michigan, Escanaba", +45.7333333333, -87.0833333333],
		["US, Michigan, Flint AP", +42.9666666667, -83.7333333333],
		["US, Michigan, Grand Rapids AP", +42.8833333333, -85.5166666667],
		["US, Michigan, Holland", +42.7, -86.1],
		["US, Michigan, Jackson AP", +42.2666666667, -84.4666666667],
		["US, Michigan, Kalamazoo", +42.2833333333, -85.6],
		["US, Michigan, Lansing AP", +42.7833333333, -84.6],
		["US, Michigan, Marquette Co", +46.5666666667, -87.4],
		["US, Michigan, Mt Pleasant", +43.5833333333, -84.7666666667],
		["US, Michigan, Muskegon AP", +43.1666666667, -86.2333333333],
		["US, Michigan, Pontiac", +42.6666666667, -83.4166666667],
		["US, Michigan, Port Huron", +42.9833333333, -82.4166666667],
		["US, Michigan, Saginaw AP", +43.5333333333, -84.0833333333],
		["US, Michigan, Sault Ste.  Marie AP (S)", +46.4666666667, -84.3666666667],
		["US, Michigan, Traverse City AP", +44.75, -85.5833333333],
		["US, Michigan, Ypsilanti", +42.2333333333, -83.5333333333],
		["US, Minnesota, Albert Lea", +43.65, -93.35],
		["US, Minnesota, Alexandria AP", +45.8666666667, -95.3833333333],
		["US, Minnesota, Bemidji AP", +47.5166666667, -94.9333333333],
		["US, Minnesota, Bcafenerd", +46.4, -94.1333333333],
		["US, Minnesota, Duluth AP", +46.8333333333, -92.1833333333],
		["US, Minnesota, Fairbault", +44.3, -93.2666666667],
		["US, Minnesota, Fergus Falls", +46.2666666667, -96.0666666667],
		["US, Minnesota, International Falls AP", +48.5666666667, -93.3833333333],
		["US, Minnesota, Mankato", +44.15, -93.9833333333],
		["US, Minnesota, Minneapolis/St. Paul AP", +44.8833333333, -93.2166666667],
		["US, Minnesota, Rochester AP", +43.9166666667, -92.5],
		["US, Minnesota, St.  Cloud AP (S)", +45.5833333333, -94.1833333333],
		["US, Minnesota, Virginia", +47.5, -92.55],
		["US, Minnesota, Willmar", +45.1166666667, -95.0833333333],
		["US, Minnesota, Winona", +44.05, -91.6333333333],
		["US, Mississippi, Biloxi--Keesler AFB", +30.4166666667, -88.9166666667],
		["US, Mississippi, Clarksdale", +34.2, -90.5666666667],
		["US, Mississippi, Columbus AFB", +33.65, -88.45],
		["US, Mississippi, Greenville AFB", +33.4833333333, -90.9833333333],
		["US, Mississippi, Greenwood", +33.5, -90.0833333333],
		["US, Mississippi, Hattiesburg", +31.2666666667, -89.25],
		["US, Mississippi, Jackson AP", +32.3166666667, -90.0833333333],
		["US, Mississippi, Laurel", +31.6666666667, -89.1666666667],
		["US, Mississippi, Mccomb AP", +31.25, -90.4666666667],
		["US, Mississippi, Meridian AP", +32.3333333333, -88.75],
		["US, Mississippi, Natchez", +31.55, -91.3833333333],
		["US, Mississippi, Tupelo", +34.2666666667, -88.7666666667],
		["US, Mississippi, Vicksburg Co", +32.4, -90.7833333333],
		["US, Missouri, Cape Girardeau", +37.2333333333, -89.5833333333],
		["US, Missouri, Columbia AP (S)", +38.9666666667, -92.3666666667],
		["US, Missouri, Farmington AP", +37.7666666667, -90.4],
		["US, Missouri, Hannibal", +39.7, -91.35],
		["US, Missouri, Jefferson City", +38.5666666667, -92.1833333333],
		["US, Missouri, Joplin AP", +37.15, -94.5],
		["US, Missouri, Kansas City AP", +39.1166666667, -94.5833333333],
		["US, Missouri, Kirksville AP", +40.1, -92.55],
		["US, Missouri, Mexico", +39.1833333333, -91.9],
		["US, Missouri, Moberly", +39.4, -92.4333333333],
		["US, Missouri, Poplar Bluff", +36.7666666667, -90.4166666667],
		["US, Missouri, Rolla", +37.9833333333, -91.7166666667],
		["US, Missouri, St. Joseph AP", +39.7666666667, -94.9166666667],
		["US, Missouri, St. Louis AP", +38.75, -90.3833333333],
		["US, Missouri, St. Louis CO", +38.65, -90.6333333333],
		["US, Missouri, Sikeston", +36.8833333333, -89.6],
		["US, Missouri, Sedalia--Whiteman AFB", +38.7166666667, -93.55],
		["US, Missouri, Sikeston", +36.8833333333, -89.6],
		["US, Missouri, Springfield AP", +37.2333333333, -93.3833333333],
		["US, Montana, Billings AP", +45.8, -108.533333333],
		["US, Montana, Bozeman", +45.7833333333, -111.15],
		["US, Montana, Butte AP", +45.95, -112.5],
		["US, Montana, Cut Bank AP", +48.6166666667, -112.366666667],
		["US, Montana, Glasgow AP (S)", +48.4166666667, -106.533333333],
		["US, Montana, Glendive", +47.1333333333, -104.8],
		["US, Montana, Great Falls AP (S)", +47.4833333333, -111.366666667],
		["US, Montana, Havre", +48.5666666667, -109.666666667],
		["US, Montana, Helena AP", +46.6, -112],
		["US, Montana, Kalispell AP", +48.3, -114.266666667],
		["US, Montana, Lewiston AP", +47.0666666667, -109.45],
		["US, Montana, Livingstown AP", +45.7, -110.433333333],
		["US, Montana, Miles City AP", +46.4333333333, -105.866666667],
		["US, Montana, Missoula AP", +46.9166666667, -114.083333333],
		["US, Nebraska, Beatrice", +40.2666666667, -96.75],
		["US, Nebraska, Chadron AP", +42.8333333333, -103.083333333],
		["US, Nebraska, Columbus", +41.4666666667, -97.3333333333],
		["US, Nebraska, Fremont", +41.4333333333, -96.4833333333],
		["US, Nebraska, Grand Island AP", +40.9833333333, -98.3166666667],
		["US, Nebraska, Hastings", +40.6, -98.4333333333],
		["US, Nebraska, Kearney", +40.7333333333, -99.0166666667],
		["US, Nebraska, Lincoln Co (S)", +40.85, -96.75],
		["US, Nebraska, McCook", +40.2, -100.633333333],
		["US, Nebraska, Norfolk", +41.9833333333, -97.4333333333],
		["US, Nebraska, North Platte AP (S)", +41.1333333333, -100.683333333],
		["US, Nebraska, Omaha AP", +41.3, -95.9],
		["US, Nebraska, Scottsbluff AP", +41.8666666667, -103.6],
		["US, Nebraska, Sidney AP", +41.2166666667, -103.1],
		["US, Nevada, Carson City", +39.1666666667, -119.766666667],
		["US, Nevada, Elko AP", +40.8333333333, -115.783333333],
		["US, Nevada, Ely AP (S)", +39.2833333333, -114.85],
		["US, Nevada, Las Vegas AP (S)", +36.0833333333, -115.166666667],
		["US, Nevada, Lovelock AP", +40.0666666667, -118.55],
		["US, Nevada, Reno AP (S)", +39.5, -119.783333333],
		["US, Nevada, Reno Co", +39.5, -119.783333333],
		["US, Nevada, Tonopah AP", +38.0666666667, -117.083333333],
		["US, Nevada, Winnemucca AP", +40.9, -117.8],
		["US, New hampshire, Berlin", +44.05, -71.0166666667],
		["US, New hampshire, Claremont", +43.0333333333, -72.0333333333],
		["US, New hampshire, Concord AP", +43.2, -71.5],
		["US, New hampshire, Keene", +42.9166666667, -72.2833333333],
		["US, New hampshire, Laconia", +43.05, -71.05],
		["US, New hampshire, Manchester, Grenier AFB", +42.9333333333, -71.4333333333],
		["US, New hampshire, Portsmouth, Pease AFB", +43.0666666667, -70.8166666667],
		["US, New jersey, Atlantic City CO", +39.3833333333, -74.4333333333],
		["US, New jersey, Long Branch", +40.3166666667, -74.0166666667],
		["US, New jersey, Newark AP", +40.7, -74.1666666667],
		["US, New jersey, New Brunswick", +40.4833333333, -74.4333333333],
		["US, New jersey, Paterson", +40.9, -74.15],
		["US, New jersey, Phillipsburg", +40.6833333333, -75.1833333333],
		["US, New jersey, Trenton Co", +40.2166666667, -74.7666666667],
		["US, New jersey, Vineland", +39.4833333333, -75],
		["US, Alamagordo, Holloman AFB", +32.85, -106.1],
		["US, Alamagordo, Albuquerque AP (S)", +35.05, -106.616666667],
		["US, Alamagordo, Artesia", +32.7666666667, -104.383333333],
		["US, Alamagordo, Carlsbad AP", +32.3333333333, -104.266666667],
		["US, Alamagordo, Clovis AP", +34.3833333333, -103.316666667],
		["US, Alamagordo, Farmington AP", +36.7333333333, -108.233333333],
		["US, Alamagordo, Gallup", +35.5166666667, -108.783333333],
		["US, Alamagordo, Grants", +35.1666666667, -107.9],
		["US, Alamagordo, Hobbs AP", +32.75, -103.216666667],
		["US, Alamagordo, Las Cruces", +32.3, -106.916666667],
		["US, Alamagordo, Los Alamos", +35.8666666667, -106.316666667],
		["US, Alamagordo, Raton AP", +36.75, -104.5],
		["US, Alamagordo, Roswell, Walker AFB", +33.3, -104.533333333],
		["US, Alamagordo, Santa Fe CO", +35.6166666667, -106.083333333],
		["US, Alamagordo, Silver City AP", +32.6333333333, -108.166666667],
		["US, Alamagordo, Socorro AP", +34.05, -106.883333333],
		["US, Alamagordo, Tucumcari AP", +35.1833333333, -103.6],
		["US, New york, Albany AP (S)", +42.75, -73.8],
		["US, New york, Albany Co", +42.65, -73.75],
		["US, New york, Auburn", +42.9, -76.5333333333],
		["US, New york, Batavia", +43, -78.1833333333],
		["US, New york, Binghamton AP", +42.2166666667, -75.9833333333],
		["US, New york, Buffalo AP", +42.9333333333, -78.7333333333],
		["US, New york, Cortland", +42.6, -76.1833333333],
		["US, New york, Dunkirk", +42.4833333333, -79.2666666667],
		["US, New york, Elmira AP", +42.1666666667, -76.9],
		["US, New york, Geneva (S)", +42.75, -76.9],
		["US, New york, Glens Falls", +43.3333333333, -73.6166666667],
		["US, New york, Gloversville", +43.0333333333, -74.35],
		["US, New york, Hornell", +42.35, -77.7],
		["US, New york, Ithaca (S)", +42.45, -76.4833333333],
		["US, New york, Jamestown", +42.1166666667, -79.2333333333],
		["US, New york, Kingston", +41.9333333333, -74],
		["US, New york, Lockport", +43.15, -79.25],
		["US, New york, Massena AP", +44.9333333333, -74.85],
		["US, New york, Newburgh, Stewart AFB", +41.5, -74.1],
		["US, New york, NYC-Central Park (S)", +40.7833333333, -73.9666666667],
		["US, New york, NYC-Kennedy AP", +40.65, -73.7833333333],
		["US, New york, NYC-La Guardia AP", +40.7666666667, -73.9],
		["US, New york, Niagara Falls AP", +43.1, -79.95],
		["US, New york, Olean", +42.2333333333, -78.3666666667],
		["US, New york, Oneonta", +42.5166666667, -75.0666666667],
		["US, New york, Oswego Co", +43.4666666667, -76.55],
		["US, New york, Plattsburg AFB", +44.65, -73.4666666667],
		["US, New york, Poughkeepsie", +41.6333333333, -73.9166666667],
		["US, New york, Rochester AP", +43.1166666667, -77.6666666667],
		["US, New york, Rome, Griffiss AFB", +43.2333333333, -75.4166666667],
		["US, New york, Schenectady (S)", +42.85, -73.95],
		["US, New york, Suffolk County AFB", +40.85, -72.6333333333],
		["US, New york, Syracuse AP", +43.1166666667, -76.1166666667],
		["US, New york, Utica", +43.15, -75.3833333333],
		["US, New york, Watertown", +43.9833333333, -76.0166666667],
		["US, North carolina, Asheville AP", +35.4333333333, -82.5333333333],
		["US, North carolina, Charlotte AP", +35.2166666667, -80.9333333333],
		["US, North carolina, Durham", +35.8666666667, -78.7833333333],
		["US, North carolina, Elizabeth City AP", +36.2666666667, -76.1833333333],
		["US, North carolina, Fayetteville, Pope AFB", +35.1666666667, -79.0166666667],
		["US, North carolina, Goldsboro,Seymour-Johnson", +35.3333333333, -77.9666666667],
		["US, North carolina, Greensboro AP (S)", +36.0833333333, -79.95],
		["US, North carolina, Greenville", +35.6166666667, -77.4166666667],
		["US, North carolina, Henderson", +36.3666666667, -78.4166666667],
		["US, North carolina, Hickory", +35.75, -81.3833333333],
		["US, North carolina, Jacksonville", +34.8333333333, -77.6166666667],
		["US, North carolina, Lumberton", +34.6166666667, -79.0666666667],
		["US, North carolina, New Bern AP", +35.0833333333, -77.05],
		["US, North carolina, Raleigh/Durham AP (S)", +35.8666666667, -78.7833333333],
		["US, North carolina, Rocky Mount", +35.9666666667, -77.8],
		["US, North carolina, Wilmington AP", +34.2666666667, -77.9166666667],
		["US, North carolina, Winston-Salem AP", +36.1333333333, -80.2166666667],
		["US, North dakota, Bismarck AP (S)", +46.7666666667, -100.75],
		["US, North dakota, Devils Lake", +48.1166666667, -98.9],
		["US, North dakota, Dickinson AP", +46.8, -102.8],
		["US, North dakota, Fargo AP", +46.9, -96.8],
		["US, North dakota, Grand Forks AP", +47.95, -97.4],
		["US, North dakota, Jamestown AP", +46.9166666667, -98.6833333333],
		["US, North dakota, Minot AP", +48.4166666667, -101.35],
		["US, North dakota, Williston", +48.15, -103.583333333],
		["US, Ohio, Akron-Canton AP", +40.9166666667, -81.4333333333],
		["US, Ohio, Ashtabula", +41.85, -80.8],
		["US, Ohio, Athens", +39.3333333333, -82.1],
		["US, Ohio, Bowling Green", +41.3833333333, -83.6333333333],
		["US, Ohio, Cambridge", +40.0666666667, -81.5833333333],
		["US, Ohio, Chillicothe", +39.35, -83],
		["US, Ohio, Cincinnati Co", +39.15, -84.5166666667],
		["US, Ohio, Cleveland AP (S)", +41.4, -81.85],
		["US, Ohio, Columbus AP (S)", +40, -82.8833333333],
		["US, Ohio, Dayton AP", +39.9, -84.2166666667],
		["US, Ohio, Defiance", +41.2833333333, -84.3833333333],
		["US, Ohio, Findlay AP", +41.0166666667, -83.6666666667],
		["US, Ohio, Fremont", +41.3333333333, -83.1166666667],
		["US, Ohio, Hamilton", +39.4, -84.5833333333],
		["US, Ohio, Lancaster", +39.7333333333, -82.6333333333],
		["US, Ohio, Lima", +40.7, -84.0333333333],
		["US, Ohio, Mansfield AP", +40.8166666667, -82.5166666667],
		["US, Ohio, Marion", +40.6, -83.1666666667],
		["US, Ohio, Middletown", +39.5166666667, -84.4166666667],
		["US, Ohio, Newark", +40.0166666667, -82.4666666667],
		["US, Ohio, Norwalk", +41.2666666667, -82.6166666667],
		["US, Ohio, Portsmouth", +38.75, -82.9166666667],
		["US, Ohio, Sandusky Co", +41.45, -82.7166666667],
		["US, Ohio, Springfield", +39.8333333333, -83.8333333333],
		["US, Ohio, Steubenville", +40.3833333333, -80.6333333333],
		["US, Ohio, Toledo AP", +41.6, -83.8],
		["US, Ohio, Warren", +41.3333333333, -80.85],
		["US, Ohio, Wooster", +40.7833333333, -81.9166666667],
		["US, Ohio, Youngstown AP", +41.2666666667, -80.6666666667],
		["US, Ohio, Zanesville AP", +39.95, -81.9],
		["US, Oklahoma, Ada", +34.7833333333, -96.6833333333],
		["US, Oklahoma, Altus AFB", +34.65, -99.2666666667],
		["US, Oklahoma, Ardmore", +34.3, -97.0166666667],
		["US, Oklahoma, Bartlesville", +36.75, -96],
		["US, Oklahoma, Chickasha", +35.05, -97.9166666667],
		["US, Oklahoma, Enid, Vance AFB", +36.35, -97.9166666667],
		["US, Oklahoma, Lawton AP", +34.5666666667, -98.4166666667],
		["US, Oklahoma, McAlester", +34.8333333333, -95.9166666667],
		["US, Oklahoma, Muskogee AP", +35.6666666667, -95.3666666667],
		["US, Oklahoma, Norman", +35.25, -97.4833333333],
		["US, Oklahoma, Oklahoma City AP (S)", +35.4, -97.6],
		["US, Oklahoma, Ponca City", +36.7333333333, -97.1],
		["US, Oklahoma, Seminole", +35.2333333333, -96.6666666667],
		["US, Oklahoma, Stillwater (S)", +36.1666666667, -97.0833333333],
		["US, Oklahoma, Tulsa AP", +36.2, -95.9],
		["US, Oklahoma, Woodward", +36.6, -99.5166666667],
		["US, Oregon, Albany", +44.6333333333, -123.116666667],
		["US, Oregon, Astoria AP (S)", +46.15, -123.883333333],
		["US, Oregon, Baker AP", +44.8333333333, -117.816666667],
		["US, Oregon, Bend", +44.0666666667, -121.316666667],
		["US, Oregon, Corvallis (S)", +44.5, -123.283333333],
		["US, Oregon, Eugene AP", +44.1166666667, -123.216666667],
		["US, Oregon, Grants Pass", +42.4333333333, -123.316666667],
		["US, Oregon, Klamath Falls AP", +42.15, -121.733333333],
		["US, Oregon, Medford AP (S)", +42.3666666667, -122.866666667],
		["US, Oregon, Pendleton AP", +45.6833333333, -118.85],
		["US, Oregon, Portland AP", +45.6, -122.6],
		["US, Oregon, Portland Co", +45.5333333333, -122.666666667],
		["US, Oregon, Roseburg AP", +43.2333333333, -123.366666667],
		["US, Oregon, Salem AP", +44.9166666667, -123.016666667],
		["US, Oregon, The Dalles", +45.6, -121.2],
		["US, Pennsylvania, Allentown AP", +40.65, -75.4333333333],
		["US, Pennsylvania, Altoona Co", +40.3, -78.3166666667],
		["US, Pennsylvania, Butler", +40.8666666667, -79.9],
		["US, Pennsylvania, Chambersburg", +39.9333333333, -77.6333333333],
		["US, Pennsylvania, Erie AP", +42.0833333333, -80.1833333333],
		["US, Pennsylvania, Harrisburg AP", +40.2, -76.7666666667],
		["US, Pennsylvania, Johnstown", +40.3166666667, -78.8333333333],
		["US, Pennsylvania, Lancaster", +40.1166666667, -76.3],
		["US, Pennsylvania, Meadville", +41.6333333333, -80.1666666667],
		["US, Pennsylvania, New Castle", +41.0166666667, -80.3666666667],
		["US, Pennsylvania, Philadelphia AP", +39.8833333333, -75.25],
		["US, Pennsylvania, Pittsburgh AP", +40.5, -80.2166666667],
		["US, Pennsylvania, Pittsburgh Co", +40.45, -80],
		["US, Pennsylvania, Reading Co", +40.3333333333, -75.6333333333],
		["US, Pennsylvania, Scranton/Wilkes-Barre", +41.3333333333, -75.7333333333],
		["US, Pennsylvania, State College (S)", +40.8, -77.8666666667],
		["US, Pennsylvania, Sunbury", +40.8833333333, -76.7666666667],
		["US, Pennsylvania, Uniontown", +39.9166666667, -79.7166666667],
		["US, Pennsylvania, Warren", +41.85, -79.1333333333],
		["US, Pennsylvania, West Chester", +39.9666666667, -75.6333333333],
		["US, Pennsylvania, Williamsport AP", +41.25, -76.9166666667],
		["US, Pennsylvania, York", +39.9166666667, -76.75],
		["US, Rhode island, Newport (S)", +41.5, -71.3333333333],
		["US, Rhode island, Providence AP", +41.7333333333, -71.4333333333],
		["US, South carolina, Anderson", +34.5, -82.7166666667],
		["US, South carolina, Charleston AFB (S)", +32.9, -80.0333333333],
		["US, South carolina, Charleston Co", +32.9, -79.9666666667],
		["US, South carolina, Columbia AP", +33.95, -81.1166666667],
		["US, South carolina, Florence AP", +34.1833333333, -79.7166666667],
		["US, South carolina, Georgetown", +33.3833333333, -79.2833333333],
		["US, South carolina, Greenville AP", +34.9, -82.2166666667],
		["US, South carolina, Greenwood", +34.1666666667, -82.1166666667],
		["US, South carolina, Orangeburg", +33.5, -80.8666666667],
		["US, South carolina, Rock Hill", +34.9833333333, -80.9666666667],
		["US, South carolina, Spartanburg AP", +34.9666666667, -82],
		["US, South carolina, Sumter, Shaw AFB", +33.9, -80.3666666667],
		["US, South dakota, Aberdeen AP", +45.45, -98.4333333333],
		["US, South dakota, Brookings", +44.3, -96.8],
		["US, South dakota, Huron AP", +44.3833333333, -98.2166666667],
		["US, South dakota, Mitchell", +43.6833333333, -98.0166666667],
		["US, South dakota, Pierre AP", +44.3833333333, -100.283333333],
		["US, South dakota, Rapid City AP (S)", +44.05, -103.066666667],
		["US, South dakota, Sioux Falls AP", +43.5666666667, -96.7333333333],
		["US, South dakota, Watertown AP", +44.9166666667, -97.15],
		["US, South dakota, Yankton", +42.9166666667, -97.3833333333],
		["US, Tennessee, Athens", +35.4333333333, -84.5833333333],
		["US, Tennessee, Bristol-Tri City AP", +36.4833333333, -82.4],
		["US, Tennessee, Chattanooga AP", +35.0333333333, -85.2],
		["US, Tennessee, Clarksville", +36.55, -87.3666666667],
		["US, Tennessee, Columbia", +35.6333333333, -87.0333333333],
		["US, Tennessee, Dyersburg", +36.0166666667, -89.4],
		["US, Tennessee, Greenville", +36.0666666667, -82.8333333333],
		["US, Tennessee, Jackson AP", +35.6, -88.9166666667],
		["US, Tennessee, Knoxville AP", +35.8166666667, -83.9833333333],
		["US, Tennessee, Memphis AP", +35.05, -90],
		["US, Tennessee, Murfreesboro", +34.9166666667, -86.4666666667],
		["US, Tennessee, Nashville AP (S)", +36.1166666667, -86.6833333333],
		["US, Tennessee, Tullahoma", +35.3833333333, -86.0833333333],
		["US, Texas, Abilene AP", +32.4166666667, -99.6833333333],
		["US, Texas, Alice AP", +27.7333333333, -98.0333333333],
		["US, Texas, Amarillo AP", +35.2333333333, -100.7],
		["US, Texas, Austin AP", +30.3, -97.7],
		["US, Texas, Bay City", +29, -95.9666666667],
		["US, Texas, Beaumont", +29.95, -94.0166666667],
		["US, Texas, Beeville", +28.3666666667, -97.6666666667],
		["US, Texas, Big Spring AP (S)", +32.3, -101.45],
		["US, Texas, Brownsville AP (S)", +25.9, -97.4333333333],
		["US, Texas, Brownwood", +31.8, -98.95],
		["US, Texas, Bryan AP", +30.6666666667, -96.55],
		["US, Texas, Corpus Christi AP", +27.7666666667, -97.5],
		["US, Texas, Corsicana", +32.0833333333, -96.4666666667],
		["US, Texas, Dallas AP", +32.85, -96.85],
		["US, Texas, Del Rio, Laughlin AFB", +29.3666666667, -100.783333333],
		["US, Texas, Denton", +33.2, -97.1],
		["US, Texas, Eagle Pass", +28.8666666667, -100.533333333],
		["US, Texas, El Paso AP (S)", +31.8, -106.4],
		["US, Texas, Fort Worth AP (S)", +32.8333333333, -97.05],
		["US, Texas, Galveston AP", +29.3, -94.8],
		["US, Texas, Greenville", +33.0666666667, -96.05],
		["US, Texas, Harlingen", +26.2333333333, -97.65],
		["US, Texas, Houston AP", +29.9666666667, -95.35],
		["US, Texas, Houston Co", +29.9833333333, -95.3666666667],
		["US, Texas, Huntsville", +30.7166666667, -95.55],
		["US, Texas, Killeen, Robert Gray AAF", +31.0833333333, -97.6833333333],
		["US, Texas, Lamesa", +32.7, -101.933333333],
		["US, Texas, Laredo AFB", +27.5333333333, -99.45],
		["US, Texas, Longview", +32.4666666667, -94.7333333333],
		["US, Texas, Lubbock AP", +33.65, -101.816666667],
		["US, Texas, Lufkin AP", +31.4166666667, -94.8],
		["US, Texas, Mcallen", +26.2, -98.2166666667],
		["US, Texas, Midland AP (S)", +31.95, -102.183333333],
		["US, Texas, Mineral Wells AP", +32.7833333333, -98.0666666667],
		["US, Texas, Palestine Co", +31.7833333333, -95.6333333333],
		["US, Texas, Pampa", +35.5333333333, -100.983333333],
		["US, Texas, Pecos", +31.4166666667, -103.5],
		["US, Texas, Plainview", +34.1833333333, -101.7],
		["US, Texas, Port Arthur AP", +29.95, -94.0166666667],
		["US, San angelo, Goodfellow AFB", +31.4333333333, -100.4],
		["US, San angelo, San Antonio AP (S)", +29.5333333333, -98.4666666667],
		["US, San angelo, Sherman, Perrin AFB", +33.7166666667, -96.6666666667],
		["US, San angelo, Snyder", +32.7166666667, -100.916666667],
		["US, San angelo, Temple", +31.1, -97.35],
		["US, San angelo, Tyler AP", +32.35, -95.2666666667],
		["US, San angelo, Vernon", +34.1666666667, -99.3],
		["US, San angelo, Victoria AP", +28.85, -96.9166666667],
		["US, San angelo, Waco AP", +31.6166666667, -97.2166666667],
		["US, San angelo, Wichita Falls AP", +33.9666666667, -98.4833333333],
		["US, Utah, Cedar City AP", +37.7, -113.1],
		["US, Utah, Logan", +41.75, -111.816666667],
		["US, Utah, Moab", +38.6, -109.6],
		["US, Utah, Ogden AP", +41.2, -112.016666667],
		["US, Utah, Price", +39.6166666667, -110.833333333],
		["US, Utah, Provo", +40.2166666667, -111.716666667],
		["US, Utah, Richfield", +38.7666666667, -112.083333333],
		["US, Utah, St George Co", +37.0333333333, -113.516666667],
		["US, Utah, Salt Lake City AP (S)", +40.7666666667, -111.966666667],
		["US, Utah, Vernal AP", +40.45, -109.516666667],
		["US, Vermont, Barre", +44.2, -72.5166666667],
		["US, Vermont, Burlington AP (S)", +44.4666666667, -73.15],
		["US, Vermont, Rutland", +43.6, -72.9666666667],
		["US, Virginia, Charlottesville", +38.0333333333, -78.5166666667],
		["US, Virginia, Danville AP", +36.5666666667, -79.3333333333],
		["US, Virginia, Fredericksburg", +38.3, -77.4666666667],
		["US, Virginia, Harrisonburg", +38.45, -78.9],
		["US, Virginia, Lynchburg AP", +37.3333333333, -79.2],
		["US, Virginia, Norfolk AP", +36.9, -76.2],
		["US, Virginia, Petersburg", +37.1833333333, -77.5166666667],
		["US, Virginia, Richmond AP", +37.5, -77.3333333333],
		["US, Virginia, Roanoke AP", +37.3166666667, -79.9666666667],
		["US, Virginia, Staunton", +38.2666666667, -78.9],
		["US, Virginia, Winchester", +39.2, -78.1666666667],
		["US, Washington, Aberdeen", +46.9833333333, -123.816666667],
		["US, Washington, Bellingham AP", +48.8, -122.533333333],
		["US, Washington, Bremerton", +47.5666666667, -122.666666667],
		["US, Washington, Ellensburg AP", +47.0333333333, -120.516666667],
		["US, Washington, Everett, Paine AFB", +47.9166666667, -122.283333333],
		["US, Washington, Kennewick", +46.2166666667, -119.133333333],
		["US, Washington, Longview", +46.1666666667, -122.933333333],
		["US, Washington, Moses Lake, Larson AFB", +47.2, -119.316666667],
		["US, Washington, Olympia AP", +46.9666666667, -122.9],
		["US, Washington, Port Angeles", +48.1166666667, -123.433333333],
		["US, Washington, Seattle-Boeing Field", +47.5333333333, -122.3],
		["US, Washington, Seattle Co (S)", +47.65, -122.3],
		["US, Washington, Seattle-Tacoma AP (S)", +47.45, -122.3],
		["US, Washington, Spokane AP (S)", +47.6333333333, -117.516666667],
		["US, Washington, Tacoma, McChord AFB", +47.25, -122.5],
		["US, Washington, Walla Walla AP", +46.1, -118.283333333],
		["US, Washington, Wenatchee", +47.4166666667, -120.316666667],
		["US, Washington, Yakima AP", +46.5666666667, -120.533333333],
		["US, West virginia, Beckley", +37.7833333333, -81.1166666667],
		["US, West virginia, Bluefield AP", +37.3, -81.2166666667],
		["US, West virginia, Charleston AP", +38.3666666667, -81.6],
		["US, West virginia, Clarksburg", +39.2666666667, -80.35],
		["US, West virginia, Elkins AP", +38.8833333333, -79.85],
		["US, West virginia, Huntington Co", +38.4166666667, -82.5],
		["US, West virginia, Martinsburg AP", +39.4, -77.9833333333],
		["US, West virginia, Morgantown AP", +39.65, -79.9166666667],
		["US, West virginia, Parkersburg Co", +39.2666666667, -81.5666666667],
		["US, West virginia, Wheeling", +40.1166666667, -80.7],
		["US, Wisconsin, Appleton", +44.25, -88.3833333333],
		["US, Wisconsin, Ashland", +46.5666666667, -90.9666666667],
		["US, Wisconsin, Beloit", +42.5, -89.0333333333],
		["US, Wisconsin, Eau Claire AP", +44.8666666667, -91.4833333333],
		["US, Wisconsin, Fond Du Lac", +43.8, -88.45],
		["US, Wisconsin, Green Bay AP", +44.4833333333, -88.1333333333],
		["US, Wisconsin, La Crosse AP", +43.8666666667, -91.25],
		["US, Wisconsin, Madison AP (S)", +43.1333333333, -89.3333333333],
		["US, Wisconsin, Manitowoc", +44.1, -87.6833333333],
		["US, Wisconsin, Marinette", +45.1, -87.6333333333],
		["US, Wisconsin, Milwaukee AP", +42.95, -87.9],
		["US, Wisconsin, Racine", +42.7166666667, -87.85],
		["US, Wisconsin, Sheboygan", +43.75, -87.7166666667],
		["US, Wisconsin, Stevens Point", +44.5, -89.5666666667],
		["US, Wisconsin, Waukesha", +43.0166666667, -88.2333333333],
		["US, Wisconsin, Wausau AP", +44.9166666667, -89.6166666667],
		["US, Wyoming, Casper AP", +42.9166666667, -106.466666667],
		["US, Wyoming, Cheyenne", +41.15, -104.816666667],
		["US, Wyoming, Cody AP", +44.55, -109.066666667],
		["US, Wyoming, Evanston", +41.2666666667, -110.95],
		["US, Wyoming, Lander AP (S)", +42.8166666667, -108.733333333],
		["US, Wyoming, Laramie AP (S)", +41.3166666667, -105.683333333],
		["US, Wyoming, Newcastle", +43.85, -104.216666667],
		["US, Wyoming, Rawlins", +41.8, -107.2],
		["US, Wyoming, Rock Springs AP", +41.6, -109],
		["US, Wyoming, Sheridan AP", +44.7666666667, -106.966666667],
		["US, Wyoming, Torrington", +42.0833333333, -104.216666667],
		["Venezuela, Caracas", +10.5, -66.9333333333],
		["Venezuela, Maracaibo", +10.65, -71.6],
		["Vietnam, Da Nang", +16.0666666667, +108.216666667],
		["Vietnam, Hanoi", +21.0333333333, +105.866666667],
		["Ho chi minh city, (Saigon)", +10.7833333333, +106.7],
		["Yugoslavia, Belgrade", +44.8, +20.4666666667],
		["Zaire, Kinshasa (Leopoldville)", -4.33333333333, +15.3],
		["Zaire, Kisangani (Stanleyville)", -0.433333333333, +15.2333333333]
	],
	koreaCitySet : cafenMsg.getObject('map_korea'),
	saveSize : [
		[700,700,'2L'],
		[700,500,'2LW'],
		[500,700,'2LH'],
		[500,500,'L'],
		[500,300,'LW'],
		[300,500,'LH'],
		[300,300,'M'],
		[300,200,'MW'],
		[200,300,'MH'],
		[200,200,'S']
	],
	getDistanceString : function(distance) {
		if (distance < 1000)
			return (distance).toFixed(3) + 'm';
		else
			return (distance/1000).toFixed(3) + 'Km';
	},
	getDistance : function(p1, p2) {
		var p1_Latitude= this.latLonToRadians(p1.Latitude);
		var p1_Longitude= this.latLonToRadians(p1.Longitude);
		var p2_Latitude= this.latLonToRadians(p2.Latitude);
		var p2_Longitude= this.latLonToRadians(p2.Longitude);	
		var R = 6371000;
		var dLat  = p2_Latitude- p1_Latitude;
		var dLong = p2_Longitude- p1_Longitude;
		var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.cos(p1_Latitude) * Math.cos(p2_Latitude) * Math.sin(dLong/2) * Math.sin(dLong/2);
		var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
		return R * c;
	},
	latLonToRadians : function( point ) {
		return point * Math.PI / 180;	
	},
	onSave : function(theURL, width, height) {
		
	},
	loadAPI : function(mapType, endFnc) {
		if (this.loadedAPI == null)
			this.loadedAPI = {YMap:false,GMap:false, DMap:false, NMap : false, VEMap : false};
		if (this.loadSchedule == null)
			this.loadSchedule = [];
		if (this.loadCheckbind == null)
			this.loadCheckbind = this.loadCheck.bind(this);
		if (cafen.checkAPI(mapType)) {
			var script_url = '';
			switch(mapType) {
				case 'DMap' : 
					script_url = 'http://apis.daum.net/maps/maps2.js?apikey=' + cafen.getAPI('DMap');
					break;
				case 'YMap' : 
					script_url = 'http://kr.open.gugi.yahoo.com/Client/AjaxMap.php?v=3.7&appid=' + cafen.getAPI('YMap');
					break;
				case 'NMap' : 
					script_url = 'http://maps.naver.com/js/naverMap.naver?key=' + cafen.getAPI('NMap');
					break;
				case 'GMap' : 
					script_url = 'http://maps.google.co.kr/maps?file=api&v=2&key=' + cafen.getAPI('GMap');
					break;
				case 'VEMap' : 
					script_url = 'http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=6.2';
					break;
			}
			if (!this.loadedAPI[mapType] && script_url != '') {
				this.loadedAPI[mapType] = true;
				this.loadSchedule.push({api : mapType, callback : endFnc});
				var scriptObj=document.createElement("script");
				scriptObj.type="text/javascript";
				scriptObj.charset="UTF-8";
				scriptObj.src= script_url;
				var targetObj=document.getElementsByTagName("head")[0];
				if(!targetObj) 
					targetObj= document.body.parentNode.appendChild(document.createElement("head"));
				targetObj.appendChild(scriptObj);
			} else
				this.loadSchedule.push({api : mapType, callback : endFnc});
			if (this.loadSchedule.length == 1)
				window.setTimeout(this.loadCheckbind,500); 
		}
	},
	loadCheck : function() {
		var loadSchedule = [];
		for(var i = 0; i < this.loadSchedule.length; i++) {
			var obj = this.loadSchedule[i];
			if (obj.api == 'GMap' && typeof GMap2 != 'undefined') {
				obj.callback();
			} else if (typeof window[obj.api] != 'undefined') {
				obj.callback();
			} else {
				loadSchedule.push(obj);
			}
		}
		this.loadSchedule = loadSchedule;
		if (this.loadSchedule.length > 0)
			window.setTimeout(this.loadCheckbind,500); 
	}
};


cafen.RMap.Mouse = function(mapObj) {
	this._mapObject = mapObj;
	this.initMouse();	
};

cafen.RMap.Mouse.prototype = {
	isHide : true,
	initPos : {x : 0, y : 0},
	sendEvent : null,
	initMouse : function(parentNode) {
		this.clickEvent = this.getEvent.bind(this);
		this.stopEvent = this.unsetEvent.bind(this);
		this.obj = new cafen.Div({event : {click : this.stopEvent},style:{position : 'relative', borderLeft : '1px solid #8a9285',borderBottom : '1px solid #8a9285', backgroundColor : '#f0ffe7', color : '#464646', width : '200px', height : 'auto', padding : '5px', textAlign : 'left', fontSize:'12px', lineHeight:'120%', zIndex : 500000, cursor : cafen.getCursor()}});
		this.obj.setOpacity(70);
		cafen.getPopup().appendChild(this.obj.getObject());
		this.unsetEvent();
		var base_left = Math.round((this._mapObject.getWidth() - 300)/2);
		var base_top = Math.round((this._mapObject.getHeight() - 70)/2);
		var textObj = new cafen.Div({style:{width : '300px', height : '30px', textAlign : 'center', padding : '5px'}});
		this.obj.appendChild(textObj);
		var barObj = new cafen.Div({style:{width : '268px', height : '22px', textAlign : 'center', backgroundImage : 'URL(' +this._mapObject.base_img_url + 'uploadprocess.gif)'}});
		this.obj.appendChild(barObj);
		this.processObj = {obj : barObj, text : textObj};
	},
	getEvent : function(lat, lon) {
		if (this.sendEvent != null)
			this.sendEvent(lat, lon);
	},
	setEvent : function(eventFnc, msg, stopFnc, cmd) {
		if (this.sendEvent != null)
			this.unsetEvent();
		this.lastCmd = cmd;
		this.initPos = cafen.cumulativeOffset(this._mapObject._mapObject.mapArea.getElement());
		this.obj.setOffset(this.initPos[0], this.initPos[1]);
		this.endEvent = (typeof stopFnc != 'function') ? null : stopFnc;
		cafen.Event.observe(document, 'keydown', this.stopEvent);
		if (this.clickEvent == null)
			this.clickEvent = this.getEvent.bind(this);
		try {
			if (this.lastCmd == 'delete')
				this._mapObject.getMarkObject().setDeleteEvent(true);
			else
				this._mapObject.mapObj.setEvent(this.clickEvent);
		} catch(ex) {}
		this.sendEvent = eventFnc;
		if (typeof msg == 'string')
			this.obj.getElement().innerHTML = msg + '<br>' +cafenMsg.get('map_0022');
		this.obj.show();
	},
	unsetEvent : function() {
		this.obj.hide();	
		if (this.sendEvent != null) {
			cafen.Event.stopObserving(document, 'keydown', this.stopEvent);
			try {
				if (this.lastCmd == 'delete')
					this._mapObject.getMarkObject().setDeleteEvent(false);
				else
					this._mapObject.mapObj.setEvent();
			} catch(ex){}
			this.lastCmd = null;
			if (this.endEvent != null) {
				this.endEvent();
				this.endEvent = null;
			}
			this.sendEvent = null;
			return false;
		}
	},
	setMsg : function(msg) {
		if (typeof msg == 'string') {
			this.processObj.text.getElement().innerHTML = msg;
			this.processObj.obj.show();
		} else {
			this.obj.getElement().innerHTML = '';
			this.processObj.obj.hide();
		}
	}
}

cafen.RMap.roadView = function(parentNode, options) {
	this._parentObj = parentNode;
	this._popupOptions = options;
	this.setOptions(cafen.extend({className :'r_popskin', tag : 'div', tplName : 'top', style : {textAlign:'center', width : this._baseSize[0]+ 'px',position :'absolute', zIndex : '500100'}, shadow : true}, options));
	this.setTitle(cafenMsg.get("map_0044"));
	this.setToolBar();
	this.initRoadView();
};

cafen.RMap.roadView.prototype = cafen.extendClass({
	_baseSize : [470, 320],
	initRoadView : function() {
		this.viewArea = new cafen.Div({style : {width : this._baseSize[0]+ 'px', height : this._baseSize[1]+ 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden', zIndex : 0}});
		this.setObject(this.viewArea);
	},
	onPopup : function() {
		if (this.roadView == null) {
			var centerObj = this._parentObj.getCenter();
			var opt = {width:this._baseSize[0] ,height:this._baseSize[1],point:new DLatLng(centerObj.Lat, centerObj.Lon)};
			this.roadView = new DRoadView(this.viewArea.getObject(),opt);
		}
	},
	setValue : function(id) {
		this.roadView.setPanoId(id);
	},
	getValue : function() {
		if (this.roadView.isLoaded())
			return this.roadView.getPanoId();
		else
			return '';
	}
},cafen.XWindow.prototype);


cafen.RMap.contentsViewer = function(parentNode) {
	this.parentNode = parentNode;
	this.initcontentsViewer();
};
cafen.RMap.contentsViewer.prototype = {
	initcontentsViewer : function() {
		this.obj = new cafen.Div({style:{position : 'absolute', textAlign : 'left', zIndex : '500000'}, attribute : {}});
		this.parentNode.linkObj.appendChild(this.obj.getObject());
		var obj_width = this.parentNode.getWidth() - 30;
		var obj_height = this.parentNode.getHeight() - 70;
		if (obj_width < 200)
			obj_width = 300;
		else if (obj_width > 500)
			obj_width = 500;
		if (obj_height < 100)
			obj_height = 200;
		else if (obj_height > 500)
			obj_height = 500;
		this.baseSize = [obj_width, obj_height];
	},
	hideLastObj : function(obj) {
		if (this.lastObj != null && this.lastObj != obj)
			this.lastObj.hide();
		this.lastObj = obj;
		if (this.lastObj != null && this.lastObj.onLoad)
			this.lastObj.onLoad();
	},
	setImage : function(imgurl) {
		if (this.imageViewer == null) {
			this.imageViewer = new cafen.XImageViewer({style : {width : this.baseSize[0] +'px', height : this.baseSize[1] +'px'}, sticker : {obj : this.parentNode._mapObject.frmSkin, x : 'center', y : 'middle'}});
			this.obj.appendChild(this.imageViewer);
		}
		this.hideLastObj(this.imageViewer);
		this.imageViewer.setImage(imgurl);
	},
	setMovie : function(imgurl) {
		if (this.movieViewer == null) {
			this.movieViewer = new cafen.XMovieViewer({style : {width : Math.round(this.baseSize[1]*1.25) +'px', height : this.baseSize[1] +'px'}, sticker : {obj : this.parentNode._mapObject.frmSkin, x : 'center', y : 'middle'}});
			this.obj.appendChild(this.movieViewer);
		}
		this.hideLastObj(this.movieViewer);
		this.movieViewer.setMovie(imgurl);
	},
	setMap : function(mapInfo) {
		if (this.mapViewer == null) {
			this.mapViewer = new cafen.XMapViewer({style : {width : this.baseSize[0] +'px', height : this.baseSize[1] +'px'}, sticker : {obj : this.parentNode._mapObject.frmSkin, x : 'center', y : 'middle'}, event : {done : this.insertMap.bind(this)}});
			this.obj.appendChild(this.mapViewer);
		}
		this.hideLastObj(this.mapViewer);
		this.mapViewer.setMap(mapInfo);
	},
	insertMap : function(obj) {
		var markInfo = {
			label : '',
			urlTxt : obj.getMap(),
			urlType : 1
		}
		this.parentNode.getPoint('addmarker', markInfo);
		this.hideLastObj(null);
	}
}

cafen.RMap.RMarker = function(parentNode) {
	this.parentNode = parentNode;
	this.initRMarker();
};
cafen.RMap.RMarker.prototype = {
	colorSet : [],
	isEditable : null,
	isHide : true,
	haveFocus : false,
	markid : null,
	markType : null,
	lastLayerObj : null,
	lastMarkerObj : null,
	lastImgObj : null,
	animateHeight : 0,
	initOffset : [8,26],
	useAnimate : false,
	colorSet : [
				['#000000','#000000','#ffffff'],
				['#000080','#000064','#d7d7d7'],
				['#008000','#006400','#d7d7d7'],
				['#008080','#006464','#d7d7d7'],
				['#800000','#640000','#d7d7d7'],
				['#800080','#640064','#d7d7d7'],
				['#808000','#646400','#d7d7d7'],
				['#808080','#646464','#7f7f7f'],
				['#c0c0c0','#8b8b8b','#272727'],
				['#0000ff','#0000ff','#7f7f7f'],
				['#00ff00','#00ff00','#7f7f7f'],
				['#00ffff','#00ffff','#7f7f7f'],
				['#ff0000','#ff0000','#7f7f7f'],
				['#ff00ff','#ff00ff','#7f7f7f'],
				['#ffff00','#ffff00','#7f7f7f']
			],
	initRMarker : function() {
		this.animateHeight = 0;
		this.useAnimate = this.parentNode.options.useAnimate;
		this.obj = new cafen.TableAuto({style:{position : 'absolute', height : 'auto', textAlign : 'left', zIndex : '500000'}, attribute : {border:0}});
		this.obj.setOpacity(80);
		this.show_icon = new cafen.Button(
				{
					attribute : {innerHTML : '&#160;'},
					style : {width : '20px', height : '30px', fontSize : '1px',overflow : 'hidden', textAlign : 'center'},
					event : {mousedown : this.moveStart.bind(this)}
				});
		this.leftSideObj = this.obj.addCell(this.show_icon);
		this.obj.addAttribute({vAlign:'top', width : '20'});
		this.viewArea = new cafen.TableAuto({attribute:{cellPadding:1}});
		this.obj.addCell(this.viewArea);
		this.textObject = new cafen.Div({className :'r_boxwhite', style : {height:'auto', width:'100px', lineHeight:'130%', padding:'2px', fontSize:'13px', border : '1px solid transparent', cursor : cafen.getCursor()}, attribute :{}});
		this.viewArea.addRow();
		this.viewArea.addCell(this.textObject);
		this.previewObject = new cafen.Div({className :'r_boxwhite', style : {height:'70px', width:'70px'}, attribute :{}});
		this.viewArea.addRow();
		this.viewArea.addCell(this.previewObject);
		this.showEditorBind = this.showEditor.bind(this, true);
		this.textObject.attachEvent('click', this.showEditorBind);
		this.options = {};
		this.parentNode._mapObject.mapArea.appendChild(this.obj);
		this._moving = false;		
		this.movestart = this.moveStart.bindAsEventListener(this);
		this.moveicon = this.moveIcon.bindAsEventListener(this);
		this.moveend = this.moveEnd.bindAsEventListener(this);
		this.parentNode.addOverlay(this);
	},
	moveStart : function(obj, e) {
		if (this.options.isEditable && cafen.Event.isLeftClick(e)) {
			this._moving = true;
			this._startPos = this.obj.getOffset();
			this._startXY  = [e.clientX, e.clientY];
			cafen.Event.observe(this.parentNode.getObject().getElement(), 'mouseup', this.moveend);
			cafen.Event.observe(this.show_icon.getElement(), 'mouseup', this.moveend);
			cafen.Event.observe(this.parentNode.getObject().getElement(), 'mousemove', this.moveicon);
			cafen.Event.stop(e);
		}
	},
	moveIcon : function(e) {
		if (!this._moving || !cafen.Event.isLeftClick(e)) return;
		var newX = this._startPos[0] + e.clientX - this._startXY[0];
		var newY = this._startPos[1] + e.clientY - this._startXY[1];
		this.obj.setStyle({left : newX + 'px', top : newY + 'px'});
		if (this.markid != null)
			this.parentNode.modifyMarker(this.markid, {x : Math.round(newX + this.initOffset[0]), y : Math.round(newY + this.initOffset[1]) });
	},
	moveEnd : function(e) {
		cafen.Event.stopObserving(this.parentNode.getObject().getElement(), 'mouseup', this.moveend);
		cafen.Event.stopObserving(this.show_icon.getElement(), 'mouseup', this.moveend);
		cafen.Event.stopObserving(this.parentNode.getObject().getElement(), 'mousemove', this.moveicon);
		if (this.markid != null)
			this.parentNode.reSynkMarker(this.markid);
		this._moving = false;
	},
	setObj : function(seqn, lat, lon, text, markType, icon, color, isEditable, extra, extraType,urlTxt, urlType) {
		if (this.markid != null && this.options.isEditMode) {
			this.parentNode.modifyMarker(this.markid, {label : this.editObject.getValue(), urlTxt : this.lastMarkerObj.urlTxt});
			if (this.markid == seqn) {
				this.markid = null;
				this.parentNode.reSynkMarker(seqn);
				return ;
			}	
		}
		this.markid = seqn;
		this.lastMarkerObj = {Lat : lat, Lon : lon, Label : text, Icon : icon, Color : color ,  Extra : extra , extraType : extraType, urlTxt : urlTxt, urlType : urlType};
		this.markType = markType;
		this.options.lat = lat;
		this.options.lon = lon;
		this.options.isEditable = isEditable;
		var xypos = this.parentNode.getLatLonXY(lat, lon);
		this.showEditor(false);
		var x = Math.round(xypos[0] - this.initOffset[0]);
		var y = Math.round(xypos[1] - this.initOffset[1]);
		if (this.useAnimate) {
			this.obj.setAnimate(null, null, x, y);
		} else
			this.obj.setOffset(x, y);
	},
	setDeleteEvent : function(bl) {
		if (this.clickEventBind == null)
			this.clickEventBind = this.clickEvent.bind(this);
		if (bl) {
			this.show_icon.attachEvent('click',this.clickEventBind);
		} else
			this.show_icon.detachEvent('click',this.clickEventBind);
	},
	clickEvent : function() {
		this.parentNode.removeMarker(this.markid);
		this.markid = null;
		this.hide();
	},
	showEditor : function(bl) {
		if (bl && this.options.isEditable) {
			if (this.markerEditor == null)
				this.markerEditor = new cafen.RMap.RMarkerEditor(this, {sticker : {obj : this.parentNode._mapObject.frmSkin, x : 'center', y : 'middle'}});
			this.markerEditor.setValue(this.markid, this.lastMarkerObj);
			this.markerEditor.onLoad();
			this.options.isEditMode =  true;
		} else {
			if (this.options.isEditMode && this.markerEditor != null)
				this.markerEditor.close();
			this.options.isEditMode =  false;
			var textData = [];
			var text = this.lastMarkerObj.Label;
			if (text != '')
				textData.push(text);
			var extra = this.lastMarkerObj.Extra;
			if (extra != '')
				textData.push(extra);
			var urlTxt = this.lastMarkerObj.urlTxt;
			var urlType = this.lastMarkerObj.urlType;
			if (urlTxt != '' && urlType != 1 && urlType != 2 && urlType != 3) 
				textData.push('<a href="'+urlTxt+'" target=_blank><u><b>L</b>ink</u></a>');
			var txt = textData.join(' <br> ');
			this.textObject.getElement().innerHTML = (txt == '') ? '&nbsp;' : txt;
			var colorNo = this.lastMarkerObj.Color;
			if (colorNo != null)
				colorNo = parseInt(colorNo);
			if (this.colorSet[colorNo] != null) {
				var colorInfo = this.colorSet[colorNo];
				this.textObject.setStyle({color : colorInfo[0], backgroundColor: colorInfo[2]});
			}
			this.viewArea.show();
			if (urlTxt != '' && (urlType == 1 || urlType == 2 || urlType == 3)) {
				var iconName = '';
				switch(urlType) {
					case 2 :
						iconName = _cafen_service_url + 'images/ico_movie.gif';
						break;
					case 3 :
						iconName = _cafen_service_url + 'images/ico_roadview.gif';
						break;
					default :
						iconName = urlTxt;
						break;
				}
				if (this.imageViewerObj == null) {
					this.imageViewerObj = new cafen.Image(iconName, {style:{width:'70px', height:'70px', cursor : cafen.getCursor()},event : {click : this.showContents.bind(this)}, scale : 'max'});
					this.previewObject.appendChild(this.imageViewerObj);
				} else
					this.imageViewerObj.setImage(iconName);
				this.previewObject.show();
			}else
				this.previewObject.hide();
		}
	},
	showContents : function() {
		if (this.lastMarkerObj.urlType == 2)
			this.parentNode.showContents(this.lastMarkerObj.urlTxt,'movie');
		 else if (this.lastMarkerObj.urlType == 3)
			this.parentNode.showContents(this.lastMarkerObj.urlTxt,'roadview');
		else
			this.parentNode.showContents(this.lastMarkerObj.urlTxt,'image');
	},
	show : function() {
		this.isHide = false;
		this.obj.show();
	},
	reDraw : function() {
		if (!this.isHide) {
			var xypos = this.parentNode.getLatLonXY(this.options.lat, this.options.lon);
			this.obj.setStyle({left : Math.round(xypos[0] - this.initOffset[0]) + 'px', top : Math.round(xypos[1] - this.initOffset[1]) + 'px'});
			this.hide();
			this.isHide = true;
		}
	},
	hide : function() {
		this.obj.hide();
	}
}

cafen.RMap.RMarkerEditor = function(parentNode, options) {
	this._markObject = parentNode;
	this._popupOptions = options;
	this.setOptions(cafen.extend({className :'r_popskin', tag : 'div', tplName : 'top', style : {textAlign:'center', width : '320px',position :'absolute', zIndex : '500100'}, shadow : true}, options));
	this.setTitle(cafenMsg.get('map_0026'));
	this.setToolBar();
	this.initRMarkerEditor();
	this.setButton(new cafen.XButton({text: cafenMsg.get('com_done'), style :{width : '40px'}, align:'center',event:{'click' : this.sendValue.bind(this)}}));
	this.setButton(new cafen.XButton({text: cafenMsg.get('com_close'), style :{width:'40px'}, align:'center',event:{'click' : this.close.bind(this)}}));
	this.setButton(new cafen.XButton({text: cafenMsg.get('ed_0026'), style :{width : '40px'}, align:'center',event:{'click' : this.deleteValue.bind(this)}}));
};

cafen.RMap.RMarkerEditor.prototype = cafen.extendClass({
	_markOptionValue : {txt : '', extra : '', extratype : '0'},
	initRMarkerEditor : function() {
		var tmpDiv = new cafen.Div({style : {padding:'3px', textAlign:'left'}});
		this.iconArea = tmpDiv.appendChild(new cafen.TableAuto({align:'center', attribute : {border:0, cellPadding:'1', cellSpacing:'1'},style : {marginTop:'3px', marginRight:'5px'}}));
		for(var i = 0; i< 80; i++) {
			if ((i % 15) == 0)
				this.iconArea.addRow();
			var x = (i % 10) * 16 ;
			var y = Math.floor(i /10) * 16;
			var icon = new cafen.XImage({className :'r_mapmark',x: x,y : y, w : 16 , h: 16}, {style:{width:'16px', height:'16px'},attribute :{unselectable : 'on'}, event : {click : this.setIconType.bind(this, i)}});
			this.iconArea.addCell(icon).setStyle({border:'1px solid transparent', padding:'1px'});
		}
		this.colorArea = tmpDiv.appendChild(new cafen.TableAuto({align:'left', attribute : {border:'0', cellPadding:'1', cellSpacing:'1'},style : {marginTop:'3px', marginRight:'5px', cursor : cafen.getCursor()}}));
		for(var i = 0; i< this._markObject.colorSet.length; i++) {
			if ((i % 15) == 0)
				this.colorArea.addRow();
			var currColor = this._markObject.colorSet[i];
			this.colorArea.addCell('&nbsp;&nbsp;').setAttribute({className : 'r_cellchecked off'}).setStyle({backgroundColor:currColor[0], fontSize:'12px', width:'15px'}).attachEvent('click', this.setColorType.bind(this, i));
		}
		this.textObject = tmpDiv.appendChild(new cafen.XTextarea({style : {height:'60px', width:'300px', margin:'2px'}, attribute :{title : cafenMsg.get('map_0038')}, event : {}}));
		this.buttonArea = tmpDiv.appendChild(new cafen.TableAuto({align:'right', attribute : {border:0},style : {marginTop:'3px', marginRight:'5px'}}));
		var urlType = {
			'0' : 'Link',
			'1' : 'Image',
			'2' : 'Movie',
			'3' : 'RoadView'
		};
		this.buttonArea.addRow();
		var iconMargin = null;
		if(cafen.browser.isIE) 
			iconMargin = '0 0 0 3px';
		else if(cafen.browser.isFF) 
			iconMargin = '-1 0 0 0px';
		else
			iconMargin = '3px 0px 3px 2px';
		this.markTypeObjs = [];
		var actionBind = this.setUrlType.bind(this);
		for(var idx in urlType) {
			var buttonTitle = urlType[idx];
			var x = 0, y = 0, bgPos = 0;
			switch(idx) {
				case '0' :
					x = 0;
					y = 80;
					bgPos = 264;
					break;
				case '1' :
					x = 32;
					y = 0;
					bgPos = 330;
					break;
				case '2' :
					x = 48;
					y = 0;
					bgPos = 330;
					break;
				case '3' :
					x = 80;
					y = 64;
					bgPos = 396;
					break;
			}
			var icon = new cafen.XImage({className :'r_mapset',x: x,y : y}, {style:{cssFloat : 'left',margin : iconMargin, width:'16px', height:'16px'},attribute :{unselectable : 'on'}});
			tmpButton = new cafen.XIcon({icon : 'r_wordset', value : idx, off : bgPos , on : 22 , over : 100, style :{width:'24px'}, attribute :{unselectable : 'on', title :buttonTitle }, event :{click : actionBind}, childNodes : [icon]}) ;
			this.markTypeObjs.push(tmpButton);
			this.buttonArea.addCell(tmpButton);
		}
		this.extraObject = tmpDiv.appendChild(new cafen.XTextarea({style : {height:'30px', width:'300px', margin:'2px'}, attribute :{title : cafenMsg.get('map_0039')}, event : {}}));
		this.setObject(tmpDiv);
	},
	setUrlType : function(obj) {
		if (obj != null) {
			var val = obj.options.value;
			this._markOptionValue.extratype = val;
		}
		for(var i = 0 ; i < this.markTypeObjs.length; i++) {
			var currObj = this.markTypeObjs[i];
			currObj.setSelected((currObj.options.value == (this._markOptionValue.extratype +'')) ? true : false);
		}
		if (this._markOptionValue.extratype == '3' && this.extraObject.getValue() == '') 
			this._markObject.parentNode.showRoadView(this.lastMarkerObj.Lat,this.lastMarkerObj.Lon, this.setRoadViewID.bind(this));
	},
	setRoadViewID : function(id) {
		this.extraObject.setValue(id);
	},
	_lastSelectedIcon : null,
	setIconType : function(val) {
		if (val != null) 
			this._markOptionValue.Icon = val;
		else
			val = this._markOptionValue.Icon;
		if (typeof val == 'number') {
			var x = (val % 15);
			var y = Math.floor(val / 15);
			if (this._lastSelectedIcon != null)
				this._lastSelectedIcon.setStyle({border:'1px solid transparent'});
			this._lastSelectedIcon =  this.iconArea.getCell(x, y);
			this._lastSelectedIcon.setStyle({border:'1px solid #51d424'});
		}
	},
	_lastSelectedColor : null,
	setColorType : function(val) {
		if (val != null) 
			this._markOptionValue.Color = val;
		else
			val = this._markOptionValue.Color;
		if (typeof val == 'number') {
			var x = (val % 15);
			var y = Math.floor(val / 15);
			if (this._lastSelectedColor != null) 
				this._lastSelectedColor.setAttribute({className : 'r_cellchecked off'});
			this._lastSelectedColor =  this.colorArea.getCell(x, y);
			this._lastSelectedColor.setAttribute({className : 'r_cellchecked on'});
		}
	},
	setValue : function(markid , markObj) {
		this.markid = markid;
		this.lastMarkerObj = markObj;
		if (this.lastMarkerObj.urlType == '')
			this.lastMarkerObj.urlType = '0';
		this._markOptionValue  = {txt : this.lastMarkerObj.Label , extra : this.lastMarkerObj.urlTxt, extratype :  this.lastMarkerObj.urlType, Icon : this.lastMarkerObj.Icon, Color : this.lastMarkerObj.Color };
		this.textObject.setValue(this._markOptionValue.txt);
		this.extraObject.setValue(this._markOptionValue.extra);
		this.setUrlType();
		this.setIconType();
		this.setColorType();
	},
	deleteValue : function() {
		if (this.markid != null) {
			this._markObject.parentNode.removeMarker(this.markid);
			this.markid = null;
			this.close();
			this._markObject.hide();
		}
	},
	sendValue : function() {
		this.lastMarkerObj.Label = this.textObject.getValue();
		this.lastMarkerObj.urlTxt = this.extraObject.getValue();
		this.lastMarkerObj.urlType = parseInt(this._markOptionValue.extratype);
		this.lastMarkerObj.Icon = parseInt(this._markOptionValue.Icon);
		this.lastMarkerObj.Color = parseInt(this._markOptionValue.Color);
		if (this.markid != null) {
			if (this.lastMarkerObj.urlTxt != '') {
				if (this.lastMarkerObj.urlType == 3) {
					var reg = [];
					if (reg = cafen.find('([0-9]+)',this.lastMarkerObj.urlTxt, true))
						this.lastMarkerObj.urlTxt = reg[1];
					else {
						this.lastMarkerObj.urlTxt = '';
						this.extraObject.setError(true);
						return true;
					}
				} else if (this.lastMarkerObj.urlType != 2) {
					var reg = [];
					if (reg = cafen.find('(https\?:\\/\\/[a-z0-9,\\|_\\-\\.\\?=&\\$\\/\\+]+)',this.lastMarkerObj.urlTxt, true))
						this.lastMarkerObj.urlTxt = reg[1];
					else {
						this.lastMarkerObj.urlTxt = '';
						this.extraObject.setError(true);
						return true;
					}
				} else {
					var theURL = this.lastMarkerObj.urlTxt;
					if (theURL.length < 10) 
						this.lastMarkerObj.urlTxt = '';
					else if (reg = cafen.find('src=([^ ]+)', theURL))
						theURL = reg[1];
					else if (reg = cafen.find('(http[^ ]+)', theURL))
						theURL = reg[1];
					else if (reg = cafen.find('(mms[^ ]+)', theURL))
						theURL = reg[1];
					else
						theURL = '';
					if (reg = cafen.find('(http[^ ]+)', theURL))
						theURL = reg[1];
					else if (reg = cafen.find('(mms[^ ]+)', theURL))
						theURL = reg[1];
					else
						theURL = '';
					if (theURL == '') {
						this.extraObject.setError(true);
						this.lastMarkerObj.urlTxt = '';
						return true;
					} else
						this.lastMarkerObj.urlTxt = theURL.split("'").join('').split('"').join('');
				}
			}
			this._markObject.options.isEditMode =  false;
			this._markObject.parentNode.modifyMarker(this.markid, {
				label : this.lastMarkerObj.Label, 
				urlTxt : this.lastMarkerObj.urlTxt, 
				urlType : this.lastMarkerObj.urlType, 
				icon : this.lastMarkerObj.Icon, 
				color : this.lastMarkerObj.Color
			});
			this._markObject.parentNode.reSynkMarker(this.markid);
		}
		this.close();
	},
	onClose : function() {
		this._markObject.options.isEditMode =  false;
	}
},cafen.XWindow.prototype);


cafen.RMap.indexMap = function(mapObj, linktype, options) {
	this._mapObject = mapObj;
	this.initOptions(cafen.extend({className :'r_btnskin', tag : 'div', style : { textAlign:'center', position :'absolute'}, shadow : true}, options));
	this.initindexMap(linktype);
};

cafen.RMap.indexMap.prototype = cafen.extendClass({
	initindexMap : function(linktype) {
		this.linkButtonId = linktype;
		switch(this.linkButtonId) {
			case 'mapkorea' :	
				this.objectSize = {width : 120, height : 230, indexImg : 'map_korea.gif', basePos : [38.6887,125.1590, 33.1458, 129.8034, 188,120], baseCity : cafen.RMap.Conf.koreaCitySet};
				break;
			case 'mapworld' :
				this.objectSize = {width : 150, height : 139, indexImg : 'map_world.gif', basePos : [130.1250,-17.2265, -58.3991, 324.4922, 109,150], baseCity : cafen.RMap.Conf.worldCitySet};
				break;
		}
		this.obj = new cafen.Div({style :{width: (this.objectSize.width + 20) +'px', height : 'auto', margin : '0', padding : '0'}});
		this.appendChild(this.obj);
		var selectResut = [];
		var idx = 0;
		for(var i = 0; i < this.objectSize.baseCity.length ; i++) {
			var cityObj = this.objectSize.baseCity[i];
			selectResut.push({value : i, text : cityObj[0]});
		}
		this.city_obj = new cafen.XSelect(selectResut, this.objectSize.width + 10,{event : {change : this.setCity.bind(this)}, dropDown : {style : {height: '150px', overflowY:'scroll', overflowX : 'hidden'}}});
		this.obj.appendChild(this.city_obj);
		this.map_obj = new cafen.Div({style :{width: (this.objectSize.width) +'px', height : (this.objectSize.height -25) +'px', margin : '0', backgroundImage : 'url(' + cafen.RMap.Conf.img_url + this.objectSize.indexImg + ')', backgroundRepeat : 'no-repeat', overflow : 'hidden', textAlign : 'left', marginTop:'5px'}});
		this.obj.appendChild(this.map_obj);
		this.map_obj.attachEvent('click', this.clickMap.bind(this));
		this.mapcursor = new cafen.Div({attribute :{unselectable : 'on'}, style: {width : '20px', height : '20px', position : 'relative', left : '0', top :'0', border : '1px solid #587a2f', backgroundColor : '#b7ff62', zIndex: '0'}});
		this.map_obj.appendChild(this.mapcursor);
		this.mapcursor.setOpacity(90);
		this.mapcursor.attachEvent('mousedown',this.startMove.bind(this));
		this.eventMoveIndex = this.moveIndex.bind(this);
		this.eventEndIndex = this.endMove.bind(this);
	},
	setCity : function(obj) {
		var idx = this.city_obj.getIndex();
		if (idx == null) {
			var val = this.city_obj.getValue();
			for(var i = 0; i < this.objectSize.baseCity.length ; i++) {
				var cityObj = this.objectSize.baseCity[i];
				if (cityObj[0].indexOf(val) == 0) {
					idx = i;
					break;		
				}
			}
			if (idx != null)
				this.city_obj.setIndex(idx);
		} else {
			var selectedCity = this.objectSize.baseCity[idx];
			var xypos = this.getLatLon2XY(selectedCity[1],selectedCity[2]);
			this.mapcursor.setStyle({left : (xypos[0] -11)+ 'px', top :(xypos[1]-11) + 'px'});
			this._mapObject.setCenter(selectedCity[1],selectedCity[2]);
		}
	},
	startMove : function(obj,e) {
		if (cafen.Event.isLeftClick(e)) {
			this._moving = true;
			this._startPos = this.mapcursor.getOffset();
			this._startXY  = cafen.pointer(e);
			this.map_obj.attachEvent('mouseup', this.eventEndIndex);
			this.map_obj.attachEvent('mousemove', this.eventMoveIndex);
		}
	},
	moveIndex : function(obj, e) {
		if (!this._moving || !cafen.Event.isLeftClick(e)) return;
		var pos = cafen.pointer(e);
		var newX = this._startPos[0] + pos[0] - this._startXY[0];
		var newY = this._startPos[1] + pos[1] - this._startXY[1];
		if (newX > 0 && newY > 0 && newX < this.objectSize.width && newY < this.objectSize.height) 
			this.mapcursor.setStyle({left : newX + 'px', top : newY + 'px'});
		else
			this.endMove();
	},
	endMove : function(obj, e) {
		this.map_obj.detachEvent('mouseup', this.eventEndIndex);
		this.map_obj.detachEvent('mousemove', this.eventMoveIndex);
		this._moving = false;
		this.updateMap();
	},
	clickMap : function(obj, e) {
		if (!this._moving) {
			var xypos = this.getEvent2XY(e);
			this.mapcursor.setStyle({left : (xypos[0] -13)+ 'px', top :(xypos[1]-11) + 'px'});
			this.updateMap();
		}
	},
	getEvent2XY : function(e) {
		var objPos = this.map_obj.cumulativeOffset();
		return [cafen.Event.pointerX(e) - objPos[0] , cafen.Event.pointerY(e) - objPos[1]];
	},
	getXY2LatLon : function(x,y) {
		var baseLatLon = this.objectSize.basePos;
		var latlon = [
			baseLatLon[0] - (baseLatLon[0] - baseLatLon[2]) * y/ baseLatLon[4],
			baseLatLon[1] - (baseLatLon[1] - baseLatLon[3]) * x/ baseLatLon[5]
			];
		if (latlon[0] >= 90)
			latlon[0] = 180 - latlon[0];
		if (latlon[1] >= 180)
			latlon[1] =  latlon[1] - 360;
		return latlon;
	},
	getLatLon2XY : function(lat,lon) {
		var baseLatLon = this.objectSize.basePos;
		var xypos = [
			(baseLatLon[1] - lon) * baseLatLon[5] / (baseLatLon[1] - baseLatLon[3]),
			(baseLatLon[0] - lat) * baseLatLon[4] / (baseLatLon[0] - baseLatLon[2])
			];
		if (this.linkButtonId == 'mapworld') {
			if (xypos[0] < 0)
				 xypos[0] += baseLatLon[5];
			if (xypos[0] > baseLatLon[5])
				 xypos[0] -= baseLatLon[5];
		}
		return xypos;
	},
	updateMap : function() {
		var pos = this.mapcursor.getOffset();
		var latlon = this.getXY2LatLon(pos[0]+13,pos[1]+11);
		this._mapObject.setCenter(latlon[0],latlon[1]);
	},
	onPopup : function() {
		var mapinfo = this._mapObject.getCenter();
		var xypos = this.getLatLon2XY(mapinfo.Lat, mapinfo.Lon);
		if (this.linkButtonId == 'mapkorea' && (xypos[0] < -10 ||  xypos[0] > 150 || xypos[1] < -10 ||  xypos[1] > 200)) {
			if (mapinfo.Zoom < 9 )
				this._mapObject.setZoom(9);
			this.city_obj.setIndex(0);
		} else {
			this.mapcursor.setStyle({left : (xypos[0] -11)+ 'px', top :(xypos[1]-11) + 'px'});
			if (this.linkButtonId == 'mapkorea' && mapinfo.Zoom < 9 )
				this._mapObject.setZoom(9);
			else if (this.linkButtonId == 'mapworld' && mapinfo.Zoom > 5 ) 
				this._mapObject.setZoom(5);
		}
	}
},cafen.XWindow.prototype);

cafen.RMap.searchResult = function(mapObj, options) {
	this._mapObject = mapObj;
	this.initOptions(cafen.extend({className :'r_btnskin', tag : 'div', style : { textAlign:'center', position :'absolute'}, shadow : true}, options));
};

cafen.RMap.searchResult.prototype = cafen.extendClass({
	onPopup : function() {
		if (this.xMenu != null)
			this.removeChild(this.xMenu);
		this.xMenu = null;
		this.queryData = this._mapObject._mapObject.queryData;
		var searchMenu = [];
		for(var i = 0; i < this.queryData.length; i++) {
			var currObj = this.queryData[i];
			var currNo = 71 + i;
			var x = (currNo % 10) * 16;
			var y = Math.floor(currNo/10) * 16;
			var icon = {className : 'r_mapmark', x : x, y : y};
			searchMenu.push({icon :  icon ,text : currObj.Address, options : currObj});
		}
		var cmdBind = this.sendValue.bind(this);
		this.xMenu = new cafen.XMenu(searchMenu, 250, {event :{select : cmdBind}, style : {overflowX : 'hidden', overflowY : 'hidden'}});
		this.appendChild(this.xMenu);
	},
	sendValue : function(obj, itemObj) {
		this.close();
		this._mapObject.setCenter(itemObj.options.itemOptions.Lat, itemObj.options.itemOptions.Lon);
	}
},cafen.XWindow.prototype);

cafen.RMap.showInfo = function(mapObj, options) {
	this._mapObject = mapObj;
	this._popupOptions = options;
	this.setOptions(cafen.extend({className :'r_popskin', tag : 'div', tplName : 'top', style : {width:'auto',textAlign:'center', position :'absolute'}, shadow : true}, options));
	this.setTitle(cafenMsg.get('map_0032'));
	this.setToolBar();
	this.contentObj = new cafen.Div({style : {margin :'5px', padding:'5px'}});
	this.setObject(this.contentObj);
}

cafen.RMap.showInfo.prototype = cafen.extendClass({
	onPopup : function() {
		if (cafen.checkAPI('GMap')) {
			var mapInfo = this._mapObject.getCenter();
			keyword = mapInfo.Lat +','+mapInfo.Lon;
			if (this.lastKeyword != keyword) {
				this.contentObj.getElement().innerHTML = cafenMsg.get('map_0008');
				this.lastKeyword = keyword;
	//			var pos = this._mapObject.getXYLatLon(0,0);
	//			var spn = (mapInfo.Lat - pos[1])+','+(pos[0] - mapInfo.Lon);
				var param = {
					q: this.lastKeyword,
	//				ll: keyword,
	//				spn: spn,
					output : 'json',
					oe:'utf8',
					hl :'ko',
					sensor:'false',
					key: cafen.getAPI('GMap')
				};
				cafen.smallSWFAjax.getFlashXml(param,this.setInfo.bind(this),'http://maps.google.com/maps/geo', true);	
			}
		} else {
			this.showMsg(cafenMsg.get('map_0031'));
		}
	},
	setInfo : function(txt) {
		if (!this._isOpen)
			this.setToggle();
		var json = cafen.getString2Json(txt);
		if (json.Status) {
			if (json.Status.code == 200 && json.Placemark)  {
				if (json.Placemark.length > 0) {
					var queryData = [];
					for(var i = 0; i< json.Placemark.length; i++) {
						var Lon = json.Placemark[i].Point.coordinates[0];
						var Lat = json.Placemark[i].Point.coordinates[1];
						var Address = json.Placemark[i].address.replace('\uB300\uD55C\uBBFC\uAD6D','');
						queryData.push({Lat : Lat, Lon : Lon, Address : Address});
					}
					if (queryData.length > 0) {
						var searchMenu = [];
						for(var i = 0; i < queryData.length; i++) {
							var currObj = queryData[i];
							var currNo = 71 + i;
							var x = (currNo % 10) * 16;
							var y = Math.floor(currNo/10) * 16;
							var icon = {className : 'r_mapmark', x : x, y : y};
							searchMenu.push({icon : icon ,text : currObj.Address, options : currObj});
						}
						var cmdBind = this.sendValue.bind(this);
						this.xMenu = new cafen.XMenu(searchMenu, 250, {event :{select : cmdBind}, style : {overflowX : 'hidden', overflowY : 'hidden'}});
						this.contentObj.getElement().innerHTML = '';
						this.contentObj.appendChild(this.xMenu);
					} else
						this.showMsg(cafenMsg.get('map_0009'));
				} else
					this.showMsg(cafenMsg.get('map_0009'));
			} else
				this.showMsg(cafenMsg.get('map_0009'));
		} else
			this.showMsg(cafenMsg.get('map_0009'));
	},
	sendValue : function(obj, itemObj) {
		this.close();
		this._mapObject.setCenter(itemObj.options.itemOptions.Lat, itemObj.options.itemOptions.Lon);
	},
	showMsg : function(msg) {
		this._mapObject.showMsg(msg);
	}
},cafen.XWindow.prototype);


cafen.RMap.areaInfo = function(mapObj, options) {
	this._mapObject = mapObj;
	this._popupOptions = options;
	this.setOptions(cafen.extend({className :'r_popskin', tag : 'div', tplName : 'both', donotresize : true, style : {width:'490px',textAlign:'center', position :'absolute'}, shadow : true}, options));
	this.setTitle(cafenMsg.get('map_0035'));
	this.setToolBar();
	this.contentsObj = new cafen.Div({style : {margin :'0px', padding:'2px', textAlign:'left'}});
	this.setObject(this.contentsObj);
	this.drawMenu();
}

cafen.RMap.areaInfo.prototype = cafen.extendClass({
	onPopup : function() {
		if (cafen.checkAPI('GMap')) {
			var mapInfo = (this.posObj == null) ? this._mapObject.getCenter() : this.posObj;
			var keyword = mapInfo.Lat +','+mapInfo.Lon;
			if (this.lastKeyword != keyword) {
				this.lastKeyword = keyword;
				var param = {
					q: this.lastKeyword,
					output : 'json',
					oe:'utf8',
					hl :'ko',
					sensor:'false',
					key: cafen.getAPI('GMap')
				};
				cafen.smallSWFAjax.getFlashXml(param,this.setKeyword.bind(this),'http://maps.google.com/maps/geo', true);	
			}
		} 
		this.selectTab(this.lastShownIdx);
	},
	setKeywordTxt : function(txt) {
		if (txt != null) {
			this.keyword = txt;
			this.inputObj.setValue(txt);
			this.webDatas = {};
		}
		this.selectTab(this.lastShownIdx);
	},
	setInputKeyword : function() {
		var txt = this.inputObj.getValue();
		if (txt.split(' ').join('') == '')
			this.inputObj.setError();
		else 
			this.setKeywordTxt(txt);
	},
	setKeyword : function(txt) {
		if (!this._isOpen)
			this.setToggle();
		var json = cafen.getString2Json(txt);
		if (json.Status) {
			if (json.Status.code == 200 && json.Placemark)  {
				if (json.Placemark.length > 0) {
					var queryData = [];
					var tmpkeyword = json.Placemark[0].address.replace('\uB300\uD55C\uBBFC\uAD6D','');
					var keyarr = tmpkeyword.split(' ');
					var keywordMap = [];
					for(var i = 0; i < keyarr.length; i++) {
						var txt = keyarr[i];
						if (txt != '' && !cafen.find('[0-9\\-]', txt))
							keywordMap.push(txt);
					}
					this.setKeywordTxt(keywordMap.join(' '));
				}
			}
		}
	},
	drawMenu : function() {
		if (this.showContentsObj == null) {
			var topSearchTbl = new cafen.TableAuto({attribute:{cellPadding: 2}});
			this.contentsObj.appendChild(topSearchTbl);
			this.inputObj = new cafen.XInput({style:{width:'150px'}, event :{end : this.setInputKeyword.bind(this)}});
			var searchButton = new cafen.XButton({text : cafenMsg.get('com_ok'),style:{width:'30px', marginLeft:'3px'}, event :{click : this.setInputKeyword.bind(this)}});
			topSearchTbl.addCell(this.inputObj);
			topSearchTbl.addCell(searchButton);
			var tabObj = cafenMsg.getObject('util_openapi');
			this._infoTab = [];
			this._infoTabObj = {}
			this.webDatas = {};
			for(var idx in tabObj) {
				var text = tabObj[idx];
				this._infoTabObj[idx] = new cafen.XTab({icon : {text : text},attribute : {}, event : {click: this.selectTab.bind(this,idx)}});
				this._infoTab.push(this._infoTabObj[idx]); 
			}
			this._infoTabMenu = new cafen.XTabMenu(this._infoTab);
			this.contentsObj.appendChild(this._infoTabMenu);
			this.showContentsObj = new cafen.Div({className :'r_btnskin',attribute:{}, style : {width:'490px', height: '150px', overflowY : 'auto'}});
			this.contentsObj.appendChild(this.showContentsObj);
			var poserbyObj = new cafen.Div({attribute:{innerHTML : '<a href="http://naver.com" target=_blank><img src="'+_cafen_service_url+'images/ico_pwbynaver.gif" border=0  align=absmiddle hspace=2></a><a href="http://daum.net" target=_blank><img src="'+_cafen_service_url+'images/ico_pwbydaum.gif" border=0 align=absmiddle hspace=2></a><a href="http://google.com" target=_blank><img src="'+_cafen_service_url+'images/ico_pwbygoogle.gif" border=0 align=absmiddle hspace=2></a>'}, style : {textAlign:'right',width:'480px', marginTop:'3px'}});
			this.appendChild(poserbyObj,'bottom');
			this.lastShownIdx = 'map';
		}
	},
	selectTab : function(idx, obj) {
		if (this._underprocess)
			return ;
		if (obj == null)
			obj = this._infoTabObj[idx];
		this._infoTabMenu.setSelected(obj);
		if (this.lastShownObj != null)
			this.lastShownObj.hide();
		if (this.webDatas['process'] != null) 
			this.webDatas['process'].hide();
		if (this.webDatas[idx] == null) {
			if (this.keyword == null || this.keyword == '') {
				this.inputObj.setError();
				this.showInputKeyword(true);
			} else {
				this.getKeywordData(idx);
			}
		} else {
			this.webDatas[idx].show();
			this.lastShownObj = this.webDatas[idx];
			if (this.webDatas['process'] != null) 
				this.webDatas['process'].hide();
		}
		this.lastShownIdx = idx;
		this.showContentsObj.onChange({scrollTop : 0}); 
	},
	showProcess : function(bl) {
		if (bl) {
			this._underprocess = true;
			if (this._processObj == null) {
				this._processObj = new cafen.Div({attribute : {innerHTML : '<img src="'+_cafen_service_url+'images/blank.gif" class="r-process">' + cafenMsg.get('com_process')}, style:{textAlign:'center', marginTop:'30px'}});
				this.showContentsObj.appendChild(this._processObj);
			} else
				this._processObj.show();
		} else {
			if (this._processObj != null && this._underprocess) 
				this._processObj.hide();
			this._underprocess = false;
		}
		this.showInputKeyword(false);
	},
	showInputKeyword : function(bl) {
		if (bl) {
			if (this._underprocess) 
				this.showProcess(false);
			this._underinputkeyword = true;
			if (this._inputkeywordObj == null) {
				this._inputkeywordObj = new cafen.Div({attribute : {innerHTML : cafenMsg.get('ed_0130')}, style:{textAlign:'center', marginTop:'30px'}});
				this.showContentsObj.appendChild(this._inputkeywordObj);
			} else
				this._inputkeywordObj.show();
		} else {
			if (this._inputkeywordObj != null && this._underinputkeyword) 
				this._inputkeywordObj.hide();
			this._underinputkeyword = false;
		}
	},
	setNullApiKey : function() {
		var tmpTbl= new cafen.TableAuto({attribute :{width :'320', cellPadding:2, cellSpacing : 2, border : 0}});
			tmpTbl.addRow();
			tmpTbl.addCell();
			tmpTbl.addCell('<u>'+this.keyword +'</u><hr>' +cafenMsg.get('com_nullkey'));
		this.webDatas[this.lastDataIdx] = tmpTbl;
		this.showContentsObj.appendChild(tmpTbl);
		this.selectTab(this.lastDataIdx);
	},
	getKeywordData : function(idx) {
		if (this._underprocess)
			return ;
		else 
			this.showProcess(true);
		this.lastDataIdx = idx;
		switch(idx) {
			case 'map' :
				if (cafen.checkAPI('GMap')) {
					var param = {
						q: this.keyword,
						output : 'json',
						oe:'utf8',
						hl :'ko',
						sensor:'false',
						key: cafen.getAPI('GMap')
					};
					cafen.smallSWFAjax.getFlashXml(param,this.setKeywordData.bind(this),'http://maps.google.com/maps/geo', true);	
				} else
					this.setNullApiKey();
				break;
			case 'vclip' :
				if (cafen.checkAPI('DAUM')) {
					var param = {
						q : this.keyword,
						pageno :1,
						result  : 10,
						output : 'rss',
						apikey : cafen.getAPI('DAUM')
					};
					cafen.smallSWFAjax.getFlashXml(param,this.setKeywordData.bind(this),'http://apis.daum.net/search/' + idx, false);
				} else
					this.setNullApiKey();
				break;
			case 'image' :
			case 'webkr' :
			case 'video' :
			case 'news' :
			case 'kin' :
				if (cafen.checkAPI('NAVER')) {
					var param = {
						query : this.keyword,
						target : idx,
						start:1,
						display : 10,
						key: cafen.getAPI('NAVER')
					};
					cafen.smallSWFAjax.getFlashXml(param,this.setKeywordData.bind(this),'http://openapi.naver.com/search', false);	
				} else
					this.setNullApiKey();
				break;	
		}
	},
	setKeywordData : function(txt) {
		this.showProcess(false);
		var titleStyle = 'white-space:nowrap;width:420px;overflow:hidden;cursor:pointer;margin:3px 3px';
		switch(this.lastDataIdx) {
			case 'map' :
				var json = cafen.getString2Json(txt);
				var tmpTbl= new cafen.TableAuto({attribute :{width :'320', cellPadding:2, cellSpacing : 2, border : 0}});
				tmpTbl.addRow();
				tmpTbl.addCell();
				tmpTbl.addStyle({width:'20px'});
				tmpTbl.addCell();
				tmpTbl.addStyle({width:'220px'});
				var datas_cnt = 0;
				if (json.Status) {
					if (json.Status.code == 200 && json.Placemark)  {
						var addHtmlBind = this.showMap.bind(this);
						if (json.Placemark.length > 0) {
							for(var i = 0; i< json.Placemark.length; i++) {
								var Lon = json.Placemark[i].Point.coordinates[0];
								var Lat = json.Placemark[i].Point.coordinates[1];
								var Address = json.Placemark[i].address.replace('\uB300\uD55C\uBBFC\uAD6D','');
								var currData = {
									title : Address, 
									lat : Lat, 
									lon : Lon, 
									playerurl : ''
								}
								tmpTbl.addRow();
								tmpTbl.addCell(new cafen.XIcon({icon:'r_mapset', off :288, on : 0,  over :16, style:{width: '16px', height:'16px'}, event : {click: addHtmlBind}, datas : currData}));
								var tmpCell = tmpTbl.addCell('<div style="'+titleStyle+'" title="'+currData.title+'">'+currData.title+'</div>');
								tmpTbl.addStyle({borderLeft:'1px dotted #d0d0d0', borderBottom:'1px dotted #d0d0d0'});
								tmpCell.attachEvent('click', this.previewMap.bind(this, {lat : Lat, lon : Lon}));
								tmpTbl.addRow();
								tmpTbl.addCell('&nbsp;');
								tmpTbl.addCell('Latitude :<u>' + Lat + '</u>, Longitude : <u>'+ Lon+'</u>');
								tmpTbl.addStyle({paddingBottom:'5px', lineHeight:'120%',wordBreak:'break-all', wordWrap:'break-word'});
								datas_cnt ++;
							}
						}
					}
				} 
				if (datas_cnt ==0) {
					tmpTbl.addRow();
					tmpTbl.addCell();
					tmpTbl.addCell('<u>'+this.keyword +'</u><hr>' +cafenMsg.get('map_0036'));
				}
				this.webDatas[this.lastDataIdx] = tmpTbl;
				this.showContentsObj.appendChild(tmpTbl);
				this.selectTab(this.lastDataIdx);
				break;
			case 'vclip' :
			case 'image' :
			case 'webkr' :
			case 'news' :
			case 'kin' :
			case 'video' :
				var tmpTbl= new cafen.TableAuto({attribute :{width :'320', cellPadding:2, cellSpacing : 2, border : 0}});
				tmpTbl.addRow();
				tmpTbl.addCell();
				tmpTbl.addStyle({width:'20px'});
				tmpTbl.addCell();
				tmpTbl.addStyle({width:'220px'});
				var rssObj = new cafen.xmlParser(txt);
				var contentsObj = null;
				var datas = [];
				if (contentsObj = rssObj.getNext()) {
					var item = null;
					while(item = contentsObj.getNext()) {
						var img = item.getNode('thumbnail');
						var player_url = item.getNode('player_url');
						var rss_url = item.getNode('link');
						if (img != '' && (cafen.find('q=(.+)', img))) 
							img = rss_url;
						var imageSize = '';
						var thumbExtra = '';
						if (this.lastDataIdx == 'image')
							imageSize = item.getNode('sizeheight') + 'px X ' +item.getNode('sizeheight') +'px'; 
						else if (this.lastDataIdx == 'vclip')
							thumbExtra = item.getNode('thumb_0') + '|' +item.getNode('thumb_1') + '|' +item.getNode('thumb_2') +'|' +item.getNode('thumb_3'); 
						datas.push({title : cafen.stripTags(item.getNode('title')), description : cafen.stripTags(item.getNode('description')), imagesize : imageSize , link : rss_url, Image : img, playerurl : player_url, thumb : thumbExtra});
					}
				}
				if (datas.length > 0) {
					var addMarkerBind = this.addMarker.bind(this);
					for(var i = 0; i < datas.length; i++) {
						var currData = datas[i];
						if (currData.Image != '' || currData.description != '' || currData.playerurl != '') {
							if (currData.playerurl != '') {
								tmpTbl.addRow();
								tmpTbl.addCell(new cafen.XIcon({icon:'r_mapset', off :272, on : 0,  over :16, style:{width: '16px', height:'16px'}, event : {click: addMarkerBind}, datas : currData}));
								var tmpCell = tmpTbl.addCell('<div style="'+titleStyle+'" title="'+currData.title+'">'+currData.title+'</div>');
								tmpTbl.addStyle({borderLeft:'1px dotted #d0d0d0', borderBottom:'1px dotted #d0d0d0'});
								tmpCell.attachEvent('click', this.showVideo.bind(this, currData.playerurl));
								if (currData.Image != '') {
									tmpTbl.addRow();
									tmpTbl.addCell('&nbsp;');
									var thumbData = [];
									thumbData.push(currData.Image);
									var imagesize = currData.thumb;
									var thumbExtra = imagesize.split("|");
									for(var j = 0 ; j < thumbExtra.length; j++) {
										if (	thumbExtra[j] != '')
											thumbData.push(thumbExtra[j]);
									}
									var thumbHtml = [];
									for(var j = 0 ; j < thumbData.length; j++) 
										thumbHtml.push('<img src="'+thumbData[j] +'" border=0 height=50 hspace=2>');
									tmpTbl.addCell(thumbHtml.join(''));
									tmpTbl.addStyle({paddingBottom:'5px', lineHeight:'120%',wordBreak:'break-all', wordWrap:'break-word', textAlign:'left'});
								}
							} else if (currData.Image != '') {
								tmpTbl.addRow();
								tmpTbl.addCell(new cafen.XIcon({icon:'r_mapset', off :256, on : 0,  over :16, style:{width: '16px', height:'16px'}, event : {click: addMarkerBind}, datas : currData}));
								var tmpCell = tmpTbl.addCell('<div style="'+titleStyle+'" title="'+currData.title+'">'+currData.title+'</div>');
								tmpTbl.addStyle({borderLeft:'1px dotted #d0d0d0', borderBottom:'1px dotted #d0d0d0'});
								tmpCell.attachEvent('click', this.showImage.bind(this, currData.Image));
								if (currData.Image != '') {
									tmpTbl.addRow();
									tmpTbl.addCell('&nbsp;');
									var thumbData = [];
									thumbData.push(currData.Image);
									var imagesize = currData.thumb;
									if (imagesize != '') {
										var thumbExtra = imagesize.split("|");
										for(var j = 0 ; j < thumbExtra.length; j++) {
											if (thumbExtra[j] != '')
												thumbData.push(thumbExtra[j]);
										}
									}
									var thumbHtml = [];
									for(var j = 0 ; j < thumbData.length; j++) 
										thumbHtml.push('<img src="'+thumbData[j] +'" border=0 height=50 hspace=2>');
									tmpTbl.addCell(thumbHtml.join(''));
									tmpTbl.addStyle({paddingBottom:'5px', lineHeight:'120%',wordBreak:'break-all', wordWrap:'break-word', textAlign:'left'});
								}
							} else if (currData.description != '') {
								tmpTbl.addRow();
								tmpTbl.addCell(new cafen.XIcon({icon:'r_mapset', off :288, on : 0,  over :16, style:{width: '16px', height:'16px'}, event : {click: addMarkerBind}, datas : currData}));
								tmpTbl.addCell('<div style="'+titleStyle+'" title="'+currData.title+'"><a href="'+currData.link+'" target=_blank>'+currData.title+'</a></div>');
								tmpTbl.addStyle({borderLeft:'1px dotted #d0d0d0', borderBottom:'1px dotted #d0d0d0'});
								tmpTbl.addRow();
								tmpTbl.addCell('&nbsp;');
								tmpTbl.addCell(cafen.longCut(currData.description, 70));
								tmpTbl.addStyle({paddingBottom:'5px', lineHeight:'120%',wordBreak:'break-all', wordWrap:'break-word', textAlign:'left'});
							}
						}
					}
				} else {
					tmpTbl.addRow();
					tmpTbl.addCell();
					tmpTbl.addCell('<u>'+this.keyword +'</u><hr>' +cafenMsg.get('map_0036'));
				}
				this.webDatas[this.lastDataIdx] = tmpTbl;
				this.showContentsObj.appendChild(tmpTbl);
				this.selectTab(this.lastDataIdx);
				break;
		}
	},
	setLatLon : function(lat, lon) {
		this.posObj = {Lat : lat, Lon: lon};
	},
	showVideo : function(imgurl) {
		this._mapObject.showContents(imgurl, 'movie');
	},
	showImage : function(imgurl) {
		this._mapObject.showContents(imgurl, 'image');
	},
	previewMap : function(obj) {
		var mapUrl = 'http://maps.google.co.kr/staticmap?center='+obj.lat+','+obj.lon+'&size=400x300&key='+cafen.getAPI('GMap')+'&maptype=satellite&zoom=15&sensor=false&format=jpg';
		this.showImage(mapUrl);
	},
	showMap : function(obj) {
		this._mapObject.showContents(obj.options.datas, 'map');
	},
	addMarker : function(obj) {
		var currData = obj.options.datas;
		var markInfo = {label : currData.title};
		if (currData.playerurl != '') {
			markInfo.urlTxt = currData.playerurl;
			markInfo.urlType = 2;
		} else if (currData.Image != '') {
			markInfo.urlTxt = currData.Image;
			markInfo.urlType = 1;
		} else {
			markInfo.urlTxt = currData.link;
			markInfo.urlType = 0;
		}
		this._mapObject.getPoint('addmarker', markInfo);
		this.close();
	},
	showMsg : function(msg) {
		this._mapObject.showMsg(msg);
	}
},cafen.XWindow.prototype);

cafen.RMap.showWeather = function(mapObj, options) {
	this._mapObject = mapObj;
	this._popupOptions = options;
	this.setOptions(cafen.extend({className :'r_popskin', tag : 'div', tplName : 'top', style : {width:'auto',textAlign:'center', position :'absolute'}, shadow : true}, options));
	this.setTitle(cafenMsg.get('map_0033'));
	this.setToolBar();
	this.contentObj = new cafen.Div({style : {margin :'5px', padding:'0px',whiteSpace: 'nowrap'}});
	this.setObject(this.contentObj);
}

cafen.RMap.showWeather.prototype = cafen.extendClass({
	onPopup : function() {
		var mapInfo = (this.posObj == null) ? this._mapObject.getCenter() : this.posObj;
		var keyword = Math.round(mapInfo.Lat*1000000) +','+Math.round(mapInfo.Lon*1000000);
		if (this.lastKeyword != keyword) {
			this.contentObj.getElement().innerHTML = '<div style="padding:10px">'+cafenMsg.get('map_0008')+ '</div>';
			this.lastKeyword = keyword;
			var param = {
				weather: ',,,'+this.lastKeyword,
				output : 'json',
				oe:'utf8',
				hl : cafenMsg.get('com_hl')
			};
			cafen.smallSWFAjax.getFlashXml(param,this.setWeather.bind(this),'http://www.google.com/ig/api', true);	
		}
	},
	setLatLon : function(lat, lon) {
		this.posObj = {Lat : lat, Lon: lon};
	},
	setWeather : function(txt) {
		this.contentObj.getElement().innerHTML = '';
		var xml = new cafen.xmlParser(txt);
		var obj = xml.getChildNodes();
		obj = obj.getElement('xml_api_reply','weather');
		var msgObj = cafenMsg.getObject('map_weather');
		var tblObj = new cafen.TableAuto({attribute : {cellpadding:2},style:{width:'230px', textAlign:'center'}});
		this.lastTbl = tblObj;
		this.contentObj.appendChild(tblObj);
		tblObj.addRow();
		var forecast_information = obj.getElement('forecast_information');
		var currentObj = new cafen.TableAuto({attribute : {cellpadding:2},style:{whiteSpace: 'nowrap', textAlign:'left'}});
		tblObj.addCell(currentObj);
		currentObj.addRow();
		var current_conditions = obj.getElement('current_conditions');
		var weatherIcon = new cafen.Image('http://www.google.com' + current_conditions.getElement('icon').get('data'),{className :'r_boxwhite', tplName : 'bottom', style :{width:'40px', height:'40px', margin:'2px'}});
		weatherIcon.appendChild(new cafen.Div({attribute :{innerHTML : msgObj.current }, style :{textAlign:'center', marginTop:'5px'}}), 'bottom');
		currentObj.addCell(weatherIcon);
		currentObj.addAttribute({rowSpan : 10, valign:'top'});
		currentObj.addRow();
		currentObj.addCell(msgObj.latlon);
		currentObj.addCell(forecast_information.getElement('latitude_e6').getInt('data')/1000000 + '/' + forecast_information.getElement('longitude_e6').getInt('data')/1000000);
		currentObj.addRow();
		currentObj.addCell(msgObj.condition);
		currentObj.addCell(current_conditions.getElement('condition').get('data'));
		currentObj.addRow();
		currentObj.addCell(msgObj.temp);
		currentObj.addCell(current_conditions.getElement('temp_c').get('data') + 'C (' + current_conditions.getElement('temp_f').get('data') + 'F)');
		currentObj.addRow();
		currentObj.addCell(current_conditions.getElement('humidity').get('data'));
		currentObj.addAttribute({colSpan : 2});
		currentObj.addRow();
		currentObj.addCell(current_conditions.getElement('wind_condition').get('data'));
		currentObj.addAttribute({colSpan : 2});
		var forecastObj = new cafen.TableAuto({attribute : {cellpadding:2, border : 0, align:'center'},style:{}});
		tblObj.addRow();
		tblObj.addCell(forecastObj);
		var forecast_conditions = obj.getElements('forecast_conditions');
		var foreCastData = [];
		for (var i = 0; i <forecast_conditions.length; i++) {
			var currObj = forecast_conditions[i];
			var day_of_week = currObj.getElement('day_of_week').get('data');
			var low = currObj.getElement('low').get('data');
			var high = currObj.getElement('high').get('data');
			var icon = currObj.getElement('icon').get('data');
			var condition = currObj.getElement('condition').get('data');
			tblObj.addRow();
			var weatherIcon = new cafen.Image('http://www.google.com' + icon,{className :'r_boxwhite', tplName : 'bottom',attribute : {title : condition + ' ' +low+'~' +high}, style :{width:'40px', height:'40px', margin:'2px'}});
			weatherIcon.appendChild(new cafen.Div({attribute :{innerHTML : day_of_week}, style :{textAlign:'center', marginTop:'5px'}}), 'bottom');
			forecastObj.addCell(weatherIcon);
		}
	},
	showMsg : function(msg) {
		this._mapObject.showMsg(msg);
	}
},cafen.XWindow.prototype);


cafen.RMap.ButtonColor = function(options) {
	this.setOptions(cafen.extend(options, {tag : 'div', attribute :{}, style : {width :'16px', height:'4px', overflow : 'hidden', backgroundColor : '#008000', marginTop: '11px'}}));
}
cafen.RMap.ButtonColor.prototype = cafen.extendClass({
	setColor : function(bgColor) {
		this.setStyle({backgroundColor : bgColor});
	}
},cafen.Element.prototype);

cafen.RMap.ColorPicker = function(mapObj, cmd, options) {
	this._mapObject = mapObj;
	this.colorCmd = cmd;
	this.initOptions(cafen.extend({className :'r_btnskin', tag : 'div', style : { textAlign:'left', position :'absolute'}, shadow : true}, options));
	this.initPicker();
}

cafen.RMap.ColorPicker.prototype = cafen.extendClass({
	_colorTable : null,
	_colorTab : [],
	_colorTabMenu : null,
	_maxLength : null,
	_selectedIdx : null,
	_baseColor : [
		{
			title : 'MS-Word',
			color :[
				 '#FFFFFF','#000000','#EEECE1','#1F497D','#4F81BD','#C0504D','#9BBB59','#8064A2','#4BACC6','#F79646',
				'#F2F2F2','#7F7F7F','#DDD9C3','#C6D9F0','#DBE5F1','#F2DCDB','#EBF1DD','#E5E0EC','#DBEEF3','#FDEADA',
				'#D8D8D8','#595959','#C4BD97','#8DB3E2','#B8CCE4','#E5B9B7','#D7E3BC','#CCC1D9','#B7DDE8','#FBD5B5',
				'#BFBFBF','#3F3F3F','#938953','#548DD4','#95B3D7','#D99694','#C3D69B','#B2A2C7','#92CDDC','#FAC08F',
				'#A5A5A5','#262626','#494429','#17365D','#366092','#953734','#76923C','#5F497A','#31859B','#E36C09',
				'#7F7F7F','#0C0C0C','#1D1B10','#0F243E','#244061','#632423','#4F6128','#3F3151','#205867','#974806',
				'#C00000','#FF0000','#FFC000','#FFFF00','#92D050','#00B050','#00B0F0','#0070C0','#002060','#7030A0'
			]
		},
		{
			title : 'Google',
			color :[
		 		'#FFFFFF','#000000','#FF0000', '#FF9900', '#FFFF00','#00FF00','#00FFFF','#0000FF','#9900FF','#FF00FF',
		 		'#F2F2F2','#7F7F7F','#F4CCCC', '#FCE5CD', '#FFF2CC','#D9EAD3','#D0E0E3','#CFE2F3','#D9D2E9','#EAD1DC',
		 		'#D8D8D8','#595959','#EA9999', '#F9CB9C', '#FFE599','#B6D7A8','#A2C4C9','#9FC5E8','#B4A7D6','#D5A6BD',
		 		'#BFBFBF','#3F3F3F','#E06666', '#F6B26B', '#FFD966','#93C47D','#76A5AF','#6FA8DC','#B4A7D6','#C27BA0',
		 		'#A5A5A5','#262626','#CC0000', '#E69138', '#F1C232','#6AA84F','#45818E','#3D85C6','#674EA7','#A64D79',
		 		'#7F7F7F','#0C0C0C','#990000', '#B45F06', '#BF9000','#38761D','#134F5C','#0B5394','#351C75','#741B47',
		 		'#C00000','#FF0000','#660000', '#783F04', '#7F6000','#274E13','#0C343D','#073763','#20124D','#4C1130'
			]
		},
		{
			title : 'Color Set1-1',
			color :[
				'#CD853F','#CD8B45','#CD904A','#D2954F','#D29A54','#D79F59','#D7A45E','#E1A963','#E1AE68','#E6B36D',
				'#DB631F','#E56D29','#E57733','#EA813D','#EF8B47','#EF904C','#F49551','#F49A56','#F49F5B','#F4A460',
				'#D2691E','#D27328','#D77D32','#D7873C','#DC9146','#E19B50','#E6A055','#EBA55A','#F0AA5F','#F5AF64',
				'#A0522D','#A05C37','#A06641','#A5704B','#AA7A55','#B4845F','#B98E69','#C39873','#CDA27D','#D7AC87',
				'#8B4513','#8B4F1D','#8B5927','#8B6331','#906D3B','#9A7745','#A4814F','#AE8B59','#B89563','#C29F6D',
				'#DA70D6','#DF75DB','#E47AE0','#E97FE5','#EE84EA','#F389EF','#F88EF4','#FD93F9','#FF98FE','#FF9DFF',
				'#BA55D3','#BF5AD8','#C45FDD','#C964E2','#CE69E7','#D36EEC','#D873F1','#DD78F6','#E27DFB','#E782FF'
			]
		},
		{
			title : 'Color Set1-1',
			color :[
				'#9932CC','#9E37D1','#A33CD6','#A841DB','#AD46E0','#B24BE5','#B750EA','#BC55EF','#C15AF4','#C65FF9',
				'#9400D3','#9905D8','#9E0ADD','#A30FE2','#A814E7','#AD19EC','#B21EF1','#B723F6','#BC28FB','#C12DFF',
				'#942894','#9E329E','#A83CA8','#B246B2','#BC50BC','#C65AC6','#D064D0','#DA6EDA','#E478E4','#EE82EE',
				'#8C008C','#960A96','#A014A0','#AA1EAA','#B428B4','#BE32BE','#C83CC8','#D246D2','#DC50DC','#E65AE6',
				'#800080','#8A0A8A','#941494','#9E1E9E','#A828A8','#B232B2','#BC3CBC','#C646C6','#D050D0','#DA5ADA',
				'#834683','#8D508D','#975A97','#A164A1','#AB6EAB','#B578B5','#BF82BF','#C98CC9','#D396D3','#DDA0DD',
				'#FFFFFF','#000000','#F2F2F2','#7F7F7F','#D8D8D8','#595959','#BFBFBF','#3F3F3F','#A5A5A5','#262626'
			]
		}
	],
	initPicker : function() {
		this._maxLength = 0;
		this._colorTab = [];
		for(var i = 0; i < this._baseColor.length; i++) {
			this._colorTab.push(new cafen.XTab({icon : {className :'r_editorset', x : i * 16, y : 144, w : 16, h:16},attribute : {title : this._baseColor[i].title}, event : {click: this.selectTab.bind(this,i)}})); 
			this._maxLength = Math.max(this._maxLength, this._baseColor[i].color.length);
		}
		this._colorTabMenu = new cafen.XTabMenu(this._colorTab);
		this.appendChild(this._colorTabMenu);
		this._colorTable = new cafen.TableAuto({className :'r_btnskin',attribute:{border :0, width :'160', cellpadding : 1, cellspacing:1, unselectable : 'on'}, style : {cursor : cafen.getCursor(), width:'160px'}});
		this.appendChild(this._colorTable);
		for(var i = 0; i< this._maxLength; i++) {
			if (i % 10 == 0)
				this._colorTable.addRow();
			var tmpcell = this._colorTable.addCell();
			this._colorTable.addStyle({width:'10%', height:'16px'});		
			tmpcell.attachEvent('click', this.sendColor.bind(this, i));
		}
		this.selectTab(0, this._colorTab[0]);
	},
	selectTab : function(idx, obj) {
		this._colorTabMenu.setSelected(obj);
		this._selectedIdx = idx;
		var baseCharSetText = this._baseColor[idx].color;
		var currLength = baseCharSetText.length;
		for(var i = 0 ; i < this._maxLength; i++) {
			var x = i % 10;
			var y = Math.floor(i/10);
			var str = (currLength > i) ? baseCharSetText[i] : 'transparent';
			this._colorTable.addStyle({backgroundColor : str}, x, y);
		}
	},
	sendColor : function(val) {
		var baseCharSetText = this._baseColor[this._selectedIdx].color;
		var currLength = baseCharSetText.length;
		var str = (currLength > val) ? baseCharSetText[val] : '';
		if (str != null && str != '')
			this._mapObject.execCommand(this.colorCmd, str);
	}
},cafen.XWindow.prototype);

cafen.RMap.markIcon = function(mapObj, options) {
	this._mapObject = mapObj;
	this.initOptions(cafen.extend({className :'r_btnskin', tag : 'div', style : { textAlign:'left', position :'absolute'}, shadow : true}, options));
	this.initIcon();
}

cafen.RMap.markIcon.prototype = cafen.extendClass({
	initIcon : function() {
		this._colorTable = new cafen.TableAuto({attribute:{border :0, width :'170', cellpadding : 2, cellSpacing:1, unselectable : 'on'}, style : {cursor : cafen.getCursor(), width:'170px'}});
		this.appendChild(this._colorTable);
		for(var i = 0; i< 80; i++) {
			if ((i % 9) == 0)
				this._colorTable.addRow();
			var x = (i % 10) * 16 ;
			var y = Math.floor(i /10) * 16;
			var icon = new cafen.XImage({className :'r_mapmark',x: x,y : y, w : 16 , h: 16}, {style:{cssFloat : 'left', width:'16px', height:'16px'},attribute :{unselectable : 'on'}, event : {click : this.sendIcon.bind(this, i)}});
			var tmpcell = this._colorTable.addCell(icon);
		}
	},
	sendIcon : function(val) {
		this._mapObject.execCommand('markicon', val);
	}
},cafen.XWindow.prototype);

/**
 * @class Null 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.NullMap = function(parentNode, apiType) {
	this.initNullMap(parentNode, apiType);
};

cafen.RMap.NullMap.prototype = {
	isUnEditable : false,
	mapFunc : {world:false, sat : true, hyb : false},
	mapObj : null,
	mapArea : null,
	markers : [],
	mapInfo : {lat : 0, lon: 0, zoom : 0, maptype : 0, apitype : 'NullMap'},
	polylineObj : null,
	mapEvent : {click:null, keydown : null},
	mapEventBind : {click:null, keydown : null},
	initNullMap : function(parentNode, apiType) {
		this.parentNode = parentNode;
		this.baseSize = [this.parentNode.getHeight(), this.parentNode.getWidth(), 1,1];
		this.mapArea = new cafen.Div({style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden'}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapInfo.apitype = apiType;
		this.mapEvent = {click : null, clickbind : this.getClickEvent.bind(this)};
		this.markerSizeObj = {size :[this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height],  coord : [this.parentNode.baseIconCoord.left, this.parentNode.baseIconCoord.top]};
		if (this.mapInfo.apitype != '')
			cafen.RMap.Conf.loadAPI(this.mapInfo.apitype, this.reDraw.bind(this));
	},
	show : function() {
		if (this.mapArea != null)
			this.mapArea.show();
	},
	hide : function() {
		if (this.mapArea != null)
			this.mapArea.hide();
	},
	reSize : function() {
		if (this.mapArea != null) {
			var height = this.parentNode.getHeight();
			height -= (this.parentNode._mapObject.toogleSatus) ? this.parentNode._mapObject.toolSize : 22;
			this.mapArea.setStyle({height:height+'px'});
		}
	},
	reDraw : function() {
		this.parentNode.changeAPI(this.mapInfo.apitype);
		if (this.parentNode.mapObj != this) {
			this.parentNode.setCenter(this.mapInfo.lat, this.mapInfo.lon);
			this.setZoom(this.mapInfo.zoom);
//			for (var i = 0; i < this.markers.length; i++) {
//				var currObj = this.markers[i];
//				this.parentNode.addMarker(currObj.lat,currObj.lon, currObj.label, currObj.markType, currObj.icon, currObj.color,currObj.isEditable, currObj.extra, currObj.extraType);
//			}
		}
	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		this.mapInfo.lat = lat;
		this.mapInfo.lon = lon;
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		level = (level == null) ? this.mapInfo.zoom : level;
		if (typeof move == 'number' && move != 0)
			level -= move;
		this.mapInfo.zoom = level;
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 */
	setMapType : function(mapType) {
		this.mapInfo.maptype = mapType;
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		return {APIType : this.mapInfo.apitype, Lat : this.mapInfo.lat, Lon : this.mapInfo.lon, Zoom : this.mapInfo.zoom};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		if (clickEvent != null && typeof clickEvent == 'function') {
			cafen.Event.observe(this.mapArea.getElement(), 'click', this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
			this.mapEvent.pos = cafen.viewportOffset(this.mapArea.getElement());
		} else {
			cafen.Event.stopObserving(this.mapArea.getElement(), 'click', this.mapEvent.clickbind);
			this.mapEvent.click = null;
		}
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(event) {
		if (this.mapEvent.click != null) {
			var pos = cafen.pointer(event);
			var x = pos[0] - this.mapEvent.pos[0];
			var y = pos[1] - this.mapEvent.pos[1];
			var latlon = this.getXYLatLon(x,y);		
			this.mapEvent.click(latlon[0], latlon[1]);
		}
	},
/**
 * 마크 설명문 보이기
 */
	showMarker : function(markerObj) {
		if (this.mapEvent.click != null)
			return ;
		var findidx = 0;
		var findMarker = null;
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (markerObj == marker.obj) {
				findidx = i;
				findMarker = marker;
			}
		}
		if (findMarker != null) {
			this.parentNode.showMarker(findidx, 
				findMarker.lat, findMarker.lon, findMarker.label, findMarker.markType, 
				findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
				findMarker.urlTxt, findMarker.urlType
			);
		}
	},
	showPolyline : function(polylineInfo) {

	},
	drawPolyline : function(polylineInfo) {

	},
/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {return null ;},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {int} markType 마크타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		var lefttop = this.getLatLonXY(lat,lon);
//		this.markerSizeObj = {size :[this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height],  coord : [this.parentNode.baseIconCoord.left, this.parentNode.baseIconCoord.top]};
		var newMarker = new cafen.XButton({style:{width:this.markerSizeObj.size[0]+'px', height:this.markerSizeObj.size[1]+ 'px', position : 'absolute', left : lefttop[0] + this.markerSizeObj.coord[0] +'px', top : lefttop[1] + this.markerSizeObj.coord[1] +'px'}});
		this.mapArea.appendChild(newMarker);
		if (isEditable || label != '' || markType == 2)
			newMarker.attachEvent('mouseover', this.showMarker.bind(this));
		this.markers.push({obj : newMarker, lat : lat, lon: lon, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : null, urlTxt : urlTxt, urlType : urlType});
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];
			for(var idx = 0 ; idx < this.markers.length ; idx++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else 
					newMarker.push(marker);
			}
			this.markers = newMarker;
		} else
			findMarker = markerObj;
	},
/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						newMarker.push(marker);
						break;
					case 2 :
						newMarker.push(marker);
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			marker.lat = pos[0];
			marker.lon = pos[1];
			marker.obj.setStyle({left : (options.x  + this.markerSizeObj.coord[0]) +'px', top : (options.y+ + this.markerSizeObj.coord[1]) +'px'});
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined')  {
			marker.icon = options.icon;
			marker.obj.changeImage(new YImage(this.parentNode.getMarkerImg(options.icon), this.markerSizeObj.size, this.markerSizeObj.info, this.markerSizeObj.coord));
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (!marker.isHidden) 
				markerinfo.push([marker.lat, marker.lon, marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
		}
		return markerinfo;
	},
/**
 * 폴리라인 다시 그리기
 * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		var xy = this.parentNode.latLngToPixel(this.mapInfo.lat, this.mapInfo.lon, this.mapInfo.zoom);
		xy.x += (x - this.baseSize[0] /2);
		xy.y += (y - this.baseSize[1] /2);
		var latlng = this.parentNode.pixelToLatLng(xy.x, xy.y, this.mapInfo.zoom);
		return [latlng.lat, latlng.lon];
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		var cxy = this.parentNode.latLngToPixel(this.mapInfo.lat, this.mapInfo.lon, this.mapInfo.zoom);
		var xy = this.parentNode.latLngToPixel(lat, lon, this.mapInfo.zoom);
		return [ xy.x - cxy.x + this.baseSize[0] /2, xy.y - cxy.y + this.baseSize[1] /2];
	}
}

/**
 * @class Yahoo 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.YMap = function(parentNode) {
	this.initYMap(parentNode);	
};

cafen.RMap.YMap.prototype = cafen.extendClass({
	isUnEditable : false,
	mapFunc : {world:true, sat : true, hyb : true},
	mapObj : null,
	markers : [],
	polylineObj : null,
	mapEvent : {click:null, clickbind : null},
	initYMap : function(parentNode) {
		this.parentNode = parentNode;
		this.mapArea = new cafen.Div({style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden'}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapObj = new YMap(this.mapArea.getObject(), YAHOO_MAP_REG, new YSize(this.parentNode.getWidth(), this.parentNode.getHeight()));
		this.setMapType(this.parentNode.getMapType());
		this.setZoom(this.parentNode.getZoom());
		this.setCenter(this.parentNode.getLatitude(), this.parentNode.getLongitude());
		var reDrawFnc = this.parentNode.reDraw.bind(this.parentNode);
		YEvent.Capture(this.mapObj, EventsList.onPan, reDrawFnc);
		YEvent.Capture(this.mapObj, EventsList.endMapDraw, reDrawFnc);
		this.markerSizeObj = {size :new YSize(this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height), info :new YCoordPoint(0, 0), coord : new YCoordPoint(this.parentNode.baseIconCoord.left, this.parentNode.baseIconCoord.top *(-0.4))};
		this.mapEvent = {click : null, clickbind : this.getClickEvent.bind(this)};

		if (this.parentNode.options.toolbaroff) {
			this.mapObj.addTypeControl();
			var zp = new YCoordPoint(10,30);
			zp.translate('right','top');
			this.mapObj.addZoomLong(zp);
		} else {

		}

	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		if (typeof pan != 'undefined' && pan)
			this.mapObj.panToLatLon(new YGeoPoint(lat, lon));
		else
			this.mapObj.drawZoomAndCenter(new YGeoPoint(lat, lon), this.mapObj.getZoomLevel());
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		level = (level == null) ? this.mapObj.getZoomLevel() : (18 - level);
		if (typeof move == 'number' && move != 0)
			level += move;
		if (level < 1) level = 1;
		if (level > 20) level = 20;
		this.mapObj.setZoomLevel(level);
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 */
	setMapType : function(mapType) {
		switch(mapType) {
			case 0 :
				this.mapObj.setMapType(YAHOO_MAP_REG);
				break;
			case 1 :
				this.mapObj.setMapType(YAHOO_MAP_SAT);
				break;
			case 2 :
			case 3 :
				this.mapObj.setMapType(YAHOO_MAP_HYB);
				break;
		}
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		var current_type = 0;
		switch(this.mapObj.getCurrentMapType()) {
			case 'YAHOO_MAP' :
				current_type = 0;
				break;
			case 'YAHOO_SAT' :
				current_type = 1;
				break;
			case 'YAHOO_HYB' :
				current_type = 2;
				break;
			default :
				current_type = 0;
				break;
		}
		return {APIType : 'YMap', Lat : this.mapObj.getCenterLatLon().Lat, Lon : this.mapObj.getCenterLatLon().Lon, Zoom : 18 - this.mapObj.getZoomLevel(), MapType : current_type};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {
		if (bl)
			this.mapObj.enableDragMap();
		else
			this.mapObj.disableDragMap();
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		if (clickEvent != null && typeof clickEvent == 'function') {
			YEvent.Capture(this.mapObj, EventsList.MouseClick, this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
		} else {
			YEvent.Remove(this.mapObj, EventsList.MouseClick, this.mapEvent.clickbind);
			this.mapEvent.click = null;
		}
		this.setPaning((this.mapEvent.click == null) ? true : false);
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(eventObj,posObj) {
		if (this.mapEvent.click != null) 
			this.mapEvent.click(posObj.Lat, posObj.Lon);
	},
/**
 * 마크 설명문 보이기
 * @param {object} markerObj 마크 Object
 */
	showMarker : function(markerObj) {
		if (this.mapEvent.click != null)
			return ;
		var findidx = 0;
		var findMarker = null;
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (markerObj == marker.obj) {
				findidx = i;
				findMarker = marker;
			}
		}
		if (findMarker != null) {
			var point = findMarker.obj.YGeoPoint;
			this.parentNode.showMarker(findidx, 
				point.Lat, point.Lon, findMarker.label, findMarker.markType, 
				findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
				findMarker.urlTxt, findMarker.urlType
			);
		}
	},
/**
 * 폴리 라인 그리기
 * @param {array} 폴리라인정보
 */
	showPolyline : function(polylineInfo) {
		if (this.lastpolylineObjs != null && this.lastpolylineObjs.length > 0) {
			for(var i = 0 ; i < this.lastpolylineObjs.length; i++) 
				this.mapObj.removeOverlay(this.lastpolylineObjs[i]);
		}
		this.lastpolylineObjs = [];
		if (polylineInfo != null) {
			for(var j = 0; j < polylineInfo.length ; j++) {
				var currObj = polylineInfo[j];
				var pointObj = [];
				for (var i = 0; i < currObj.lines.length;  i++) {
					var posObj = currObj.lines[i];
					pointObj.push(new YGeoPoint(posObj[1],posObj[0]));
				}
				var polylineObj = new YPolyline(pointObj,currObj.color, currObj.weight);
				this.mapObj.addOverlay(polylineObj);
				this.lastpolylineObjs.push(polylineObj);
			}
		}
	},
/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {
		var findMarker = this.markers[idx];
		if (findMarker != null) {
			var point = findMarker.obj.YGeoPoint;
			return {Lat : point.Lat, Lon : point.Lon, Label : findMarker.label, markType : findMarker.markType, 
				Icon : findMarker.icon, Color : findMarker.color, Extra : findMarker.extra, extraType : findMarker.extraType}
		} else
			return {};
	},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {
		this.parentNode.hideMarker();
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {boolean} markType 마크 타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (markType > 0) 
			this.removeMarkerPos(lat,lon);
		if (typeof markColor == 'undefined')
			markColor = 0;
		if (typeof markIcon == 'undefined')
			markIcon = 0;
		if (typeof isEditable == 'undefined')
			isEditable = false;
		if (typeof extra == 'undefined')
			extra = '';
		var geoPoint = new YGeoPoint(lat, lon);
		var newMarker= new YMarker(geoPoint, new YImage(this.parentNode.getMarkerImg(markIcon), this.markerSizeObj.size, this.markerSizeObj.info, this.markerSizeObj.coord));
		if (isEditable || label != '' || urlTxt != '' || markType == 2)
			YEvent.Capture(newMarker, EventsList.MouseOver, this.showMarker.bind(this,newMarker));
		this.mapObj.addOverlay(newMarker);
		var polylineObj = null;
		if (extra != '' && extratype == 'polyline') {
			polylineInfo = this.parentNode.getExtraPolyline(extra, 'WGS',5);
			var lineObj = [];
			for (var i = 0; i < polylineInfo.lines.length;  i++) {
				var posObj = polylineInfo.lines[i];
				lineObj.push(new YGeoPoint(posObj[0],posObj[1]));
			}
			polylineObj = new YPolyline(lineObj, polylineInfo.color, polylineInfo.weight);
			this.mapObj.addOverlay(polylineObj);
		}
		this.markers.push({obj : newMarker, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : polylineObj, urlTxt : urlTxt, urlType : urlType});
		if (markType == 2)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];
			for(var idx = 0 ; idx < this.markers.length; idx ++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else
					newMarker.push(marker);
			}
			if (isPolyline)
				this.drawPolyline();
		} else
			findMarker = markerObj;
		if (addedObj != null)
			this.mapObj.removeOverlay(addedObj);
		this.mapObj.removeOverlay(findMarker);
		YEvent.ClearAll(findMarker);
	},
/**
 * 마크 삭제하기
 * @param {object} lat 위도
 * @param {object} lon 경도
 */
	removeMarkerPos : function(lat, lon) {
		var isPolyline = false;
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var point = marker.obj.YGeoPoint;
			if (point.Lat == lat && point.Lon == lon) {
				if (marker.markType == 2)
					isPolyline = true;
				this.removeMarker(marker.obj,marker.addedObj);
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (isPolyline)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var newMarker = [];
		for(var i = 0 ; i < this.markers.length; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						marker.obj.hide();
						if (marker.addedObj != null)
							marker.addedObj.hide();
						marker.isHidden = true;
						newMarker.push(marker);
						break;
					case 2 :
						marker.obj.unhide();
						if (marker.addedObj != null) 
							marker.addedObj.unhide();
						marker.isHidden = false;
						newMarker.push(marker);
						break;
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				return true;
		}
		this.markers = newMarker;
		if (markType == 2) {
			this.drawPolyline(markHidden);
			this.showPolyline();
		}
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			marker.obj.setYGeoPoint(new YGeoPoint(pos[0],pos[1]));
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined')  {
			marker.icon = options.icon;
			marker.obj.changeImage(new YImage(this.parentNode.getMarkerImg(options.icon), this.markerSizeObj.size, this.markerSizeObj.info, this.markerSizeObj.coord));
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var checkBounds = this.parentNode.isInBounds.bind(this.parentNode);
		var Bound = this.mapObj.getBoundsLatLon();
		this.parentNode.setBounds(Bound.LatMax, Bound.LonMin, Bound.LatMin, Bound.LonMax);
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (typeof markTypes[marker.markType] != 'undefined' && markTypes[marker.markType] && !marker.isHidden) {
				var point = marker.obj.YGeoPoint;
				if (marker.markType == 2 || checkBounds(point.Lat, point.Lon))
					markerinfo.push([point.Lat, point.Lon, marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
			}
		}
		return markerinfo;
	},
/**
 * 폴리라인 다시 그리기
 * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {
		switch(markHidden) {
			case 1 : 
				if (	this.polylineObj != null) 
					this.polylineObj.hide();
				break;
//			case 2 :
//				if (	this.polylineObj != null) 
//					this.polylineObj.unhide();
//				break;
			default : 
				if (	this.polylineObj != null) {
					this.mapObj.removeOverlay(this.polylineObj);
					this.polylineObj = null;
				}
				var lineObj = [];
				var lastObj = null;
				var distance_killometers = 0;
				for(var i = 0 ; i < this.markers.length ; i++) {
					var marker = this.markers[i];
					if (marker.markType == 2) {
						var geoPoint = marker.obj.YGeoPoint;
						if (lastObj != null) {
							var distObj = geoPoint.distance(lastObj);
							distance_killometers += distObj.kilometers*1000;
							marker.extra = cafen.RMap.Conf.getDistanceString(distance_killometers);
						} else
							marker.extra = cafenMsg.get('map_0029');
						lineObj.push(geoPoint);
						lastObj = geoPoint;
					}
				}
				if (lineObj.length > 0) {
					this.polylineObj = new YPolyline(lineObj,this.parentNode.basePolyline.color ,this.parentNode.basePolyline.weight);
					this.mapObj.addOverlay(this.polylineObj);
				}
				break;
		}
	},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		var pos = this.mapObj.convertXYLatLon(new YCoordPoint(x,y));
		return [pos.Lat, pos.Lon];
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		var pos = this.mapObj.convertLatLonXY(new YGeoPoint(lat, lon));
		return [pos.x, pos.y];
	}
},cafen.RMap.NullMap.prototype);



/**
 * @class Daum 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.DMap = function(parentNode) {
	this.initDMap(parentNode);
};

cafen.RMap.DMap.prototype = cafen.extendClass({
	isUnEditable : false,
	mapFunc : {world:false, sat : true, hyb : true},
	mapObj : null,
	markers : [],
	polylineObj : null,
	mapEvent : {click:null, clickbind : null},
	initDMap : function(parentNode) {
		this.parentNode = parentNode;
		this.mapArea = new cafen.Div({style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden', zIndex : 0}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapObj = new DMap(this.mapArea.getObject(), {width :this.parentNode.getWidth() +'px', height: (this.parentNode.getHeight() -55)+'px', level : 10, autosize : false});
		this.mapObj.convertXYLatLon = function(x, y) {
			var latlngBounds = this.getBound();
			var mapSize = this.main.options;
			return [
				(y - 27) /mapSize.height * ( latlngBounds.bottom - latlngBounds.top) + latlngBounds.top,
				(x -10)/mapSize.width * ( latlngBounds.right - latlngBounds.left) + latlngBounds.left
			];
		};
		this.mapObj.convertLatLonXY = function(lat, lon) {
			var latlngBounds = this.getBound();
			var mapSize = this.main.options;
			return [
				Math.round((lon - latlngBounds.left) / (latlngBounds.right - latlngBounds.left) * mapSize.width) + 10,
				Math.round((latlngBounds.top - lat) / ( latlngBounds.top - latlngBounds.bottom) * mapSize.height) + 27,
			];
		};
		this.mapObj.getDistance = function(Spoint, Epoint) {
			Spoint = this.getTransCoord(Spoint,"wgs84", "congnamul");
			Epoint = this.getTransCoord(Epoint,"wgs84", "congnamul");
			return this.main.distance.calculate(Spoint,Epoint);
		};
		this.setMapType(this.parentNode.getMapType());
		this.setZoom(this.parentNode.getZoom());
		this.setCenter(this.parentNode.getLatitude(), this.parentNode.getLongitude());
		var reDrawFnc = this.parentNode.reDraw.bind(this.parentNode);
//		DEvent.addListener(this.mapObj, "move", reDrawFnc);
		DEvent.addListener(this.mapObj, "redraw", reDrawFnc);
		DEvent.addListener(this.mapObj, "moveend", reDrawFnc);
		this.markerSizeObj = {size :new DSize(this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height), info :new DPoint(0, 0), coord : new DPoint(this.parentNode.baseIconCoord.left, Math.round(this.parentNode.baseIconCoord.top))};
		this.mapEvent = {click : null, clickbind : this.getClickEvent.bind(this)};
		if (this.parentNode.options.toolbaroff) {
			this.mapObj.addControl(new DMapTypeControl());
			this.mapObj.addControl(new DZoomControl());  
		} else {
			this.mapObj.setDisableContextMenu();
//			this.mapObj.disableDoubleClickZoom();
//			this.mapObj.disableDragging();
		}
	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon,pan) {
		if (this.parentNode.isInKorea(lat, lon)) {
			if (typeof pan != 'undefined' && pan) {
				this.mapObj.panTo(new DPoint(lon,lat));
			}else {
				this.mapObj.setCenter(new DPoint(lon,lat),this.mapObj.getLevel());
			}
		}
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		if (typeof move == 'number' && move != 0) {
			if (move < 0) 
				this.mapObj.zoomIn();
			else
				this.mapObj.zoomOut();
		} else {
			level = (level == null) ? this.mapObj.getLevel() : (20 - level);
			if (typeof move == 'number' && move != 0) 
				level += move;
			if (level < 1) level = 1;
			else if (level > 12) level = 12;
			this.mapObj.setCenter(this.mapObj.getCenter(), level);
		}
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 */
	setMapType : function(mapType) {
		switch(mapType) {
			case 0 :
				this.mapObj.setMapType('TYPE_MAP');
				break;
			case 1 :
				this.setHybrid(false);
				break;
			case 2 :
				this.setHybrid(true);
				break;
			case 3 :
				break;
		}
	},
	setHybrid : function(bl) {
		try {
			if (bl) {
				if (this.roadViewAreaOverlay == null) 
					this.roadViewAreaOverlay = new DRoadViewOverlay(this.mapObj); //로드뷰 오버레이 생성
				else 
					this.roadViewAreaOverlay.show();
			} else {
				if (this.roadViewAreaOverlay != null) 
					this.roadViewAreaOverlay.hide();
				this.mapObj.setMapType("TYPE_SKYVIEW");
			}
		} catch(ex) {}
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		var current_type = 0;
		switch(this.mapObj.getMapType()) { 
			case 'TYPE_MAP' :
				current_type = 0;
				break;
			case 'TYPE_SKYVIEW' :
				current_type = (this.mapObj.isHybrid()) ? 2 : 1;
				break;
		}
		return {APIType : 'DMap', Lat : this.mapObj.getCenter().y, Lon : this.mapObj.getCenter().x, Zoom : (20 - this.mapObj.getLevel()), MapType : current_type};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {
		if (bl) {
			this.mapObj.enableDragging();
			this.mapObj.enableScrollWheelZoom();
		} else {
			this.mapObj.disableDragging();
			this.mapObj.disableScrollWheelZoom();
		}
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		if (clickEvent != null && typeof clickEvent == 'function') {
			this.setZoom();
			if (this.mapEvent.click != null)
				DEvent.removeListener(this.mapObj, "click", this.mapEvent.clickbind);
			DEvent.addListener(this.mapObj, "click", this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
		} else {
			DEvent.removeListener(this.mapObj, "click", this.mapEvent.clickbind);
			this.mapEvent.click = null;
		}
//		this.setPaning((this.mapEvent.click == null) ? true : false);
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(posObj) {
		if (this.mapEvent.click != null) {
			this.mapEvent.click(posObj.y, posObj.x);
		}
	},
/**
 * 마크 설명문 보이기
 * @param {object} markerObj 마크 Object
 */
	showMarker : function(markerObj) {
		if (this.mapEvent.click != null)
			return ;
		var findidx = 0;
		var findMarker = null;
		var idx = 0;
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (markerObj == marker.obj) {
				findidx = i;
				findMarker = marker;
			}
		}
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			this.parentNode.showMarker(findidx, 
				point.y, point.x, findMarker.label, findMarker.markType, 
				findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
				findMarker.urlTxt, findMarker.urlType
			);
		}
	},
/**
 * 폴리 라인 그리기
 * @param {array} 폴리라인정보
 */
	showPolyline : function(polylineInfo) {
		if (this.lastpolylineObjs != null && this.lastpolylineObjs.length > 0) {
			for(var i = 0 ; i < this.lastpolylineObjs.length; i++) 
				this.mapObj.removeOverlay(this.lastpolylineObjs[i]);
		}
		this.lastpolylineObjs = [];
		if (polylineInfo != null) {
			for(var j = 0; j < polylineInfo.length ; j++) {
				var currObj = polylineInfo[j];
				var pointObj = [];
				for (var i = 0; i < currObj.lines.length;  i++) {
					var posObj = currObj.lines[i];
					pointObj.push(new DLatLng(posObj[1],posObj[0]));
				}
				polylineObj = new DPolyline(pointObj, {strokeColor : currObj.color, strokeWeight: currObj.weight});
				this.mapObj.addOverlay(polylineObj);
				this.lastpolylineObjs.push(polylineObj);
			}
		}
	},
/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {
		var findMarker = this.markers[idx];
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			return {Lat : point.y, Lon : point.x, Label : findMarker.label, markType : findMarker.markType, 
				Icon : findMarker.icon, Color : findMarker.color, Extra : findMarker.extra, extraType : findMarker.extraType}
		} else
			return {};
	},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {
		this.parentNode.hideMarker();
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {boolean} markType 마크 타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (!this.parentNode.isInKorea(lat, lon)) 
			return ;
//		if (markType > 0) 
//			this.removeMarkerPos(lat,lon);
		if (typeof markColor == 'undefined')
			markColor = 0;
		if (typeof markIcon == 'undefined')
			markIcon = 0;
		if (typeof isEditable == 'undefined')
			isEditable = false;
		if (typeof extra == 'undefined')
			extra = '';
		var geoPoint = new DPoint(lon, lat);
		var newMarker= new DMark(geoPoint, {
			mark : new DIcon(this.parentNode.getMarkerImg(markIcon), this.markerSizeObj.size),
			draggable : false,
			removable : false,
			clickable  : false,
			offset : this.markerSizeObj.coord
		});
		if (isEditable || label != '' || urlTxt != '' || markType == 2)
			DEvent.addListener(newMarker, "mouseover", this.showMarker.bind(this, newMarker));
		this.mapObj.addOverlay(newMarker);
		var polylineObj = null;
		if (extra != '' && extratype == 'polyline') {
			polylineInfo = this.parentNode.getExtraPolyline(extra, 'WGS',5);
			var lineObj = [];
			for (var i = 0; i < polylineInfo.lines.length;  i++) {
				var posObj = polylineInfo.lines[i];
				lineObj.push(new DLatLng(posObj[0],posObj[1]));
			}
			polylineObj = new DPolyline(lineObj, {strokeColor :polylineInfo.color, strokeWeight: polylineInfo.weight});
			this.mapObj.addOverlay(polylineObj);
		}
		this.markers.push({obj : newMarker, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : polylineObj, urlTxt : urlTxt, urlType : urlType});
		if (markType == 2)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];			
			for(var idx = 0; idx < this.markers.length; idx++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else
					newMarker.push(marker);
			}
			this.markers = newMarker;
			if (isPolyline)
				this.drawPolyline();
		} else
			findMarker = markerObj;
		if (addedObj != null)
			this.mapObj.removeOverlay(addedObj);
		this.mapObj.removeOverlay(findMarker);
	},
/**
 * 마크 삭제하기
 * @param {object} lat 위도
 * @param {object} lon 경도
 */
	removeMarkerPos : function(lat, lon) {
		var isPolyline = false;
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var point = marker.obj.getPoint();
			if (point.y == lat && point.x == lon) {
				if (marker.markType == 2)
					isPolyline = true;
				this.removeMarker(marker.obj,marker.addedObj);
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (isPolyline)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						marker.obj.hide();
						if (marker.addedObj != null)
							marker.addedObj.hide();
						marker.isHidden = true;
						newMarker.push(marker);
						break;
					case 2 :
						marker.obj.show();
						if (marker.addedObj != null) 
							marker.addedObj.show();
						marker.isHidden = false;
						newMarker.push(marker);
						break;
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (markType == 2) {
			this.drawPolyline(markHidden);
			this.showPolyline();
		}
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			marker.obj.setPoint(new DLatLng(pos[0],pos[1]));
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined')  {
			marker.icon = options.icon;
			var obj = marker.obj.getObject();
			if (obj.childNodes[0] != null && obj.childNodes[0].childNodes[0] != null && obj.childNodes[0].childNodes[0].tagName == 'IMG')
				obj.childNodes[0].childNodes[0].setAttribute('src',this.parentNode.getMarkerImg(options.icon));
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var checkBounds = this.parentNode.isInBounds.bind(this.parentNode);
		var Bound = this.mapObj.getBound();
		this.parentNode.setBounds(Bound.top, Bound.left, Bound.bottom, Bound.right);
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (typeof markTypes[marker.markType] != 'undefined' && markTypes[marker.markType] && !marker.isHidden) {
				var point = marker.obj.getPoint();
				if (marker.markType == 2 || checkBounds(point.y, point.x))
					markerinfo.push([point.y, point.x, marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
			}
		}
		return markerinfo;
	},
/**
 * 폴리라인 다시 그리기
 * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {
		switch(markHidden) {
			case 1 : 
				if (	this.polylineObj != null) 
					this.mapObj.removeOverlay(this.polylineObj);
				break;
			case 2 :
				if (	this.polylineObj != null) 
					this.mapObj.addOverlay(this.polylineObj);
				break;
			default : 
				if (	this.polylineObj != null) {
					this.mapObj.removeOverlay(this.polylineObj);
					this.polylineObj = null;
				}
				var lineObj = [];
				var lastObj = null;
				var distance_killometers = 0;
				var distObj = this.mapObj.getDistance.bind(this.mapObj);
				for(var i = 0 ; i < this.markers.length ; i++) {
					var marker = this.markers[i];
					if (marker.markType == 2) {
						var geoPoint = marker.obj.getPoint();
						if (lastObj != null) {
							var dist = distObj(lastObj, geoPoint);
							distance_killometers += dist;
							marker.extra = cafen.RMap.Conf.getDistanceString(distance_killometers);
						} else
							marker.extra = cafenMsg.get('map_0029');
						lineObj.push(geoPoint);
						lastObj = geoPoint;
					}
				}
				if (lineObj.length > 1) {
					try {
						this.polylineObj = new DPolyline(lineObj, {coordinate  : 'wgs84', strokeColor : this.parentNode.basePolyline.color, strokeWeight: this.parentNode.basePolyline.weight, strokeOpacity : 0.5, fillOpacity  : 0.0});
						this.mapObj.addOverlay(this.polylineObj);
					} catch(ex) {
					}
				}
				break;
		}
	},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		var pos = this.mapObj.convertXYLatLon(x,y);
		return [pos[0], pos[1]];
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		var pos = this.mapObj.convertLatLonXY(lat, lon);
		return [pos[0], pos[1]];
	}
},cafen.RMap.NullMap.prototype);


/**
 * @class Naver 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.NMap = function(parentNode) {
	this.initNMap(parentNode);	
};

cafen.RMap.NMap.prototype = cafen.extendClass({
	isUnEditable : false,
	mapFunc : {world:false, sat : true, hyb : true},
	mapObj : null,
	markers : [],
	polylineObj : null,
	eventSeqn : false,
	mapEvent : {click:null, clickbind : null},
	initNMap : function(parentNode) {
		this.parentNode = parentNode;
		this.eventSeqn = false;
		this.mapArea = new cafen.Div({style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden'}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapObj = new NMap(this.mapArea.getElement(), this.parentNode.getWidth(), this.parentNode.getHeight());
		this.mapObj.mapSize = {width : (this.parentNode.getWidth() - 55), height : this.parentNode.getHeight()};
		var reDrawFnc = this.parentNode.reDraw.bind(this.parentNode);
		NEvent.addListener(this.mapObj, "redraw", reDrawFnc);
		NEvent.addListener(this.mapObj, "drag", reDrawFnc);
		this.mapObj.convertXYLatLon = function(x, y) {
			var latlngBounds = this.getBound();
			var mapSize = this.mapSize;
			return [
				(y + 28) /mapSize.height * ( latlngBounds[3] - latlngBounds[1]) + latlngBounds[1],
				(x + 2) /mapSize.width * ( latlngBounds[2] - latlngBounds[0]) + latlngBounds[0]
			];
		};
		this.mapObj.convertLatLonXY = function(lat, lon) {
			var latlngBounds = this.getBound();
			var mapSize = this.mapSize;
			return [
				(lon - latlngBounds[0]) / (latlngBounds[2] - latlngBounds[0]) * mapSize.width -2 ,
				(lat - latlngBounds[1]) / ( latlngBounds[3] - latlngBounds[1]) * mapSize.height - 28,
			];
		};
		this.setMapType(this.parentNode.getMapType());
		this.setZoom(this.parentNode.getZoom());
		this.setCenter(this.parentNode.getLatitude(), this.parentNode.getLongitude());
		this.markerSizeObj = {size :new NSize(this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height), info :new NSize(0, 0), coord : new NSize(this.parentNode.baseIconCoord.left *(-1), this.parentNode.baseIconCoord.top *(-1))};
		this.mapEvent = {click: null, clickbind : this.getClickEvent.bind(this)};
		if (this.parentNode.options.toolbaroff) {
			this.mapObj.addControl(new NMapBtns());
			this.mapObj.addControl(new NZoomControl());
		} else {
			this.mapObj.disableWheelZoom();	
		}
	},
/**
 * WGS 를 katech 좌표로 변환
 * @param {float} lat 위도 y 좌표
 * @param {float} lon 경도 x 좌표
 * @return {array} [위도,경도]
 */
	getWGSkatech : function(lon, lat) {
		if (this.TM128_naver == null || this.WGS84_google == null) {
			this.TM128_naver = new CS(csList.TM128_katech_3param);
			this.WGS84_google = new CS(csList.GOOGLE_WGS84);
		}
		var p = new PT(lon, lat);
		cs_transform(this.WGS84_google,this.TM128_naver, p);
		return [p.y, p.x];
	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		if (typeof pan != 'undefined' && pan) {
			if (this.parentNode.isInKorea(lon, lat)) {
				var pos = this.getLatLonXY(lon, lat);
				this.mapObj.pan(pos[0] - this.parentNode.getWidth()/2 , this.parentNode.getHeight()/2 - pos[1]);
			}
		} else if (this.parentNode.isInKorea(lat, lon)) {
			var pos = this.getWGSkatech(lon,lat);
			this.mapObj.setCenter(new NPoint(pos[1],pos[0]));
		}
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		level = (level == null) ? this.mapObj.getZoom() : (18 - level);
		if (typeof move == 'number' && move != 0)
			level += move;
		if (level < 1) level = 1;
		if (level > 11) level = 11;
		this.mapObj.setZoom(level);
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 */
	setMapType : function(mapType) {
		switch(mapType) {
			case 0 :
				this.mapObj.setMapMode(0);
				break;
			case 1 :
				this.mapObj.setMapMode(2);
				break;
			case 2 :
				this.mapObj.setMapMode(1);
				break;
		}
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		var pos = this.parentNode.getConvPositionType(this.mapObj.getCenter().getX(), this.mapObj.getCenter().getY(), 'TM128');
		var mapType = 0;
		switch(this.mapObj.getMapMode()) {
			case 0 :
				mapType = 0;
				break;
			case 1 :
				mapType = 2;
				break;
			case 2 :
				mapType = 1;
				break;
			default :
				mapType = 0;
				break;
		}				
		return {APIType : 'NMap', Lat : pos[1], Lon : pos[0], Zoom : 18 - this.mapObj.getZoom(), MapType : mapType};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {
		if (bl)
			this.mapObj.enableDrag();
		else
			this.mapObj.disableDrag();
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		this.eventSeqn = false;
		if (clickEvent != null && typeof clickEvent == 'function') {
			NEvent.addListener(this.mapObj, "click", this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
		} else {
			this.mapEvent.click = null;
			NEvent.removeListener(this.mapObj, "click", this.mapEvent.clickbind);
		}
		this.setPaning((this.mapEvent.click == null) ? true : false);
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(posObj) {
		if (this.mapEvent.click != null && this.eventSeqn) {
			var pos = this.parentNode.getConvPositionType(posObj.getX(), posObj.getY(), 'TM128');
			this.mapEvent.click(pos[1], pos[0]);
		}
		this.eventSeqn = true;
	},
/**
 * 마크 설명문 보이기
 * @param {object} markerObj 마크 Object
 */
	showMarker : function(markerObj) {
		if (this.mapEvent.click != null)
			return ;
		var findidx = 0;
		var findMarker = null;
		var idx = 0;
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (markerObj == marker.obj) {
				findidx = i;
				findMarker = marker;
			}
		}
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			var pos = this.parentNode.getConvPositionType(point.getY(), point.getX(), 'TM128');
			this.parentNode.showMarker(findidx, 
				pos[1], pos[0], findMarker.label, findMarker.markType, 
				findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
				findMarker.urlTxt, findMarker.urlType
			);
		}
	},
/**
 * 폴리 라인 그리기
 * @param {array} 폴리라인정보
 */
	showPolyline : function(polylineInfo) {
		if (this.lastpolylineObjs != null && this.lastpolylineObjs.length > 0) {
			for(var i = 0 ; i < this.lastpolylineObjs.length; i++) 
				this.mapObj.removeOverlay(this.lastpolylineObjs[i]);
		}
		this.lastpolylineObjs = [];
		if (polylineInfo != null) {
			for(var j = 0; j < polylineInfo.length ; j++) {
				var currObj = polylineInfo[j];
				var polylineObj = new NPolyline();
				polylineObj.setColor(currObj.color);
				polylineObj.setWeight(currObj.weight);
				for (var i = 0; i < currObj.lines.length;  i++) {
					var posObj = currObj.lines[i];
					polylineObj.addPoints(new NPoint(posObj[0],posObj[1]));
				}
				this.mapObj.addOverlay(polylineObj);
				this.lastpolylineObjs.push(polylineObj);
			}
		}
	},
/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {
		var findMarker = this.markers[idx];
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			var pos = this.parentNode.getConvPositionType(point.getX(), point.getY(),'TM128');
			return {Lat : pos[1] , Lon : pos[0], Label : findMarker.label, markType : findMarker.markType, 
				Icon : findMarker.icon, Color : findMarker.color, Extra : findMarker.extra, extraType : findMarker.extraType}
		} else
			return {};
	},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {
		this.parentNode.hideMarker();
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {int} markType 마크타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (!this.parentNode.isInKorea(lat, lon)) 
			return ;
//		if (markType > 0) 
//			this.removeMarkerPos(lat,lon);
		if (typeof markColor == 'undefined')
			markColor = 0;
		if (typeof markIcon == 'undefined')
			markIcon = 0;
		if (typeof isEditable == 'undefined')
			isEditable = false;
		if (typeof extra == 'undefined')
			extra = '';
		var pos = this.getWGSkatech(lon,lat);
		var newMarker= new NMark(new NPoint(pos[1],pos[0]), new NIcon(this.parentNode.getMarkerImg(markIcon), this.markerSizeObj.size, this.markerSizeObj.coord));
		if (isEditable || label != '' || urlTxt != '' || markType == 2)
			NEvent.addListener(newMarker, "mouseover", this.showMarker.bind(this, newMarker));
		this.mapObj.addOverlay(newMarker);
		var polylineObj = null;
		if (extra != '' && extratype == 'polyline') {
			polylineInfo = this.parentNode.getExtraPolyline(extra, 'TM128',2);
			var polylineObj = new NPolyline();
			polylineObj.setColor(polylineInfo.color);
			polylineObj.setWeight(this.parentNode.basePolyline.weight);
			for (var i = 0; i < polylineInfo.lines.length;  i++) {
				var posObj = polylineInfo.lines[i];
				polylineObj.addPoints(new NPoint(posObj[1],posObj[0]));
			}
			this.mapObj.addOverlay(polylineObj);
		}
		this.markers.push({obj : newMarker, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : polylineObj, urlTxt : urlTxt, urlType : urlType});
		if (markType == 2)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];
			for(var idx = 0; idx < this.markers.length; idx++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else
					newMarker.push(marker);
			}
			this.markers = newMarker;
			if (isPolyline)
				this.drawPolyline();
		} else
			findMarker = markerObj;
		if (addedObj != null) 
			this.mapObj.removeOverlay(addedObj);
		this.mapObj.removeOverlay(findMarker);
	},
/**
 * 위도 경도로 마크 삭제하기
 * @param {object} lat 위도
 * @param {object} lon 경도
 */
	removeMarkerPos : function(lat, lon) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var point = marker.obj.getPoint();
			var pos = this.parentNode.getConvPositionType(point.getX(),point.getY(),'TM128');
			if (pos[1] == lat && pos[0] == lon) 
				this.removeMarker(marker.obj, marker.addedObj);
			else
				newMarker.push(marker);
		}
		this.markers = newMarker;
	},
/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						marker.obj.hide();
						if (marker.addedObj != null)
							marker.addedObj.hide();
						marker.isHidden = true;
						newMarker.push(marker);
						break;
					case 2 :
						marker.obj.show();
						if (marker.addedObj != null)
							marker.addedObj.show();
						marker.isHidden = false;
						newMarker.push(marker);
						break;
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (markType == 2) {
			this.drawPolyline(markHidden);
			this.showPolyline();
		}
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			pos = this.getWGSkatech(pos[0], pos[1]);
			marker.obj.setPoint(new NPoint(pos[0],pos[1]));
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined')  {
			marker.icon = options.icon;
			marker.obj.setIconImage(this.parentNode.getMarkerImg(options.icon));
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var Bound = this.mapObj.getBound();
		this.parentNode.setBounds(Bound[1],Bound[0],Bound[3],Bound[2]);
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (typeof markTypes[marker.markType] != 'undefined' && markTypes[marker.markType] && !marker.isHidden) {
				var point = marker.obj.getPoint();
				if (marker.markType == 2 || this.parentNode.isInBounds(point.getY(), point.getX())) {
					var pos =  this.parentNode.getConvPositionType(point.getX(), point.getY(), 'TM128');
					markerinfo.push([pos[1], pos[0], marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
				}
			}
		}
		return markerinfo;
	},
/**
 * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {
		switch(markHidden) {
			case 1 : 
				if (	this.polylineObj != null) 
					this.polylineObj.hide();
				break;
			case 2 :
				if (	this.polylineObj != null) 
					this.polylineObj.show();
				break;
			default : 
				if (	this.polylineObj != null) {
					this.mapObj.removeOverlay(this.polylineObj);
					this.polylineObj = null;
				}
				var lineObj = [];
				var lastObj = null;
				var distance_killometers = 0;
				for(var i = 0; i < this.markers.length; i++) {
					var marker = this.markers[i];
					if (marker.markType == 2) {
						var geoPoint = marker.obj.getPoint();
						if (lastObj != null) {
							distance_killometers += geoPoint.distance(lastObj);
							marker.extra = cafen.RMap.Conf.getDistanceString(distance_killometers);
						} else
							marker.extra = cafenMsg.get('map_0029');
						lineObj.push(geoPoint);
						lastObj = geoPoint;
					}
				}
				if (lineObj.length > 0) {
					this.polylineObj = new NPolyline();
					this.polylineObj.setColor(this.parentNode.basePolyline.color);
					this.polylineObj.setWeight(this.parentNode.basePolyline.weight);
					for (var i = 0; i < lineObj.length;  i++)
						this.polylineObj.addPoints(lineObj[i]);
					this.mapObj.addOverlay(this.polylineObj);
				}
				break;
		}
	},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		var pos = this.mapObj.convertXYLatLon(x, y);
		return this.parentNode.getConvPositionType(pos[0], pos[1],'TM128');
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		var pos = this.getWGSkatech(lon, lat);
		return this.mapObj.convertLatLonXY(pos[1],pos[0]);
	}
},cafen.RMap.NullMap.prototype);


/**
 * @class Google 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.GMap = function(parentNode) {
	this.initGMap(parentNode);
};

cafen.RMap.GMap.prototype = cafen.extendClass({
	isUnEditable : false,
	mapFunc : {world:true, sat : true, hyb : true},
	mapObj : null,
	markers : [],
	polylineObj : null,
	mapEvent : {click:null, keydown : null},
	initGMap : function(parentNode) {
		this.parentNode = parentNode;
		this.mapArea = new cafen.Div({style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden'}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapObj = new GMap2(this.mapArea.getObject(), { size: new GSize(this.parentNode.getWidth(), this.parentNode.getHeight())});
		var reDrawFnc = this.parentNode.reDraw.bind(this.parentNode);
		GEvent.addListener(this.mapObj, "drag", reDrawFnc);
		GEvent.addListener(this.mapObj, "zoomend", reDrawFnc);
		GEvent.addListener(this.mapObj, "move", reDrawFnc);
		this.mapObj.convertXYLatLon = function(x, y) {
			var point = this.fromContainerPixelToLatLng({x : x, y : y});
			return [point.lat() , point.lng()];
		};
		this.mapObj.convertLatLonXY = function(lat, lon) {
			var point = this.fromLatLngToContainerPixel(new GLatLng(lat, lon));
			return [point.x , point.y];
		}
		this.baseIcon = new GIcon();
		this.baseIcon.iconSize = new GSize(this.parentNode.baseIconSize.width, this.parentNode.baseIconSize.height);
		this.baseIcon.iconAnchor = new GPoint(this.parentNode.baseIconCoord.left *(-1), this.parentNode.baseIconCoord.top *(-1));
		this.setCenter(this.parentNode.getLatitude(), this.parentNode.getLongitude());
		this.setMapType(this.parentNode.getMapType());
		this.setZoom(this.parentNode.getZoom());
		this.markerSizeObj = {size : this.baseIcon.iconSize, coord : this.baseIcon.iconAnchor };
		this.mapEvent = {click : null, clickbind : this.getClickEvent.bind(this), handle : null};

		if (this.parentNode.options.toolbaroff) {
			this.mapObj.addControl(new GMapTypeControl()); 
			this.mapObj.addControl(new GLargeMapControl3D(), new GControlPosition(G_ANCHOR_TOP_RIGHT, new GSize(10,30)));
		} else {
			this.mapObj.disableScrollWheelZoom();
		}
	},
/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		if (typeof pan != 'undefined' && pan) 
			this.mapObj.panTo(new GLatLng(lat,lon));
		else
			this.mapObj.setCenter(new GLatLng(lat,lon));
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		level = (level == null) ? this.mapObj.getZoom() : level;
		if (typeof move == 'number' && move != 0)
			level += move *(-1);
		this.mapObj.setZoom(level);
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 * @param {boolean} rotateType 맵타잎로테이션
 */
	setMapType : function(mapType, rotateType) {
		switch(mapType) {
			case 0 :
				this.mapObj.setMapType(G_NORMAL_MAP);
				break;
			case 1 :
				this.mapObj.setMapType(G_SATELLITE_MAP);
				break;
			case 2 :
				var oldMapType = this.mapObj.getCurrentMapType();
				if (typeof rotateType == 'undefined' || !rotateType || oldMapType == G_NORMAL_MAP || oldMapType == G_SATELLITE_MAP)
					this.mapObj.setMapType(G_HYBRID_MAP);
				else if (oldMapType == G_HYBRID_MAP)
					this.mapObj.setMapType(G_PHYSICAL_MAP);
				else
					this.mapObj.setMapType(G_HYBRID_MAP);
				break;
			case 3 :
				this.mapObj.setMapType(G_PHYSICAL_MAP);
				break;
		}
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		var current_type = 0;
		var currentMapType = this.mapObj.getCurrentMapType();
		switch(currentMapType) {
			case G_NORMAL_MAP :
				current_type = 0;
				break;
			case G_SATELLITE_MAP :
				current_type = 1;
				break;
			case G_HYBRID_MAP :
				current_type = 2;
				break;
			case G_PHYSICAL_MAP :
				current_type = 3;
				break;
			default : 
				current_type = 0;
				break;;
		}
		return {APIType : 'GMap', Lat : this.mapObj.getCenter().lat(), Lon : this.mapObj.getCenter().lng(), Zoom : this.mapObj.getZoom(), MapType : current_type};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {
		if (bl) {
			this.mapObj.enableDoubleClickZoom();
			this.mapObj.enableDragging();
		} else {
			this.mapObj.disableDoubleClickZoom()
			this.mapObj.disableDragging();
		}
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		if (clickEvent != null && typeof clickEvent == 'function') {
			this.setPaning(false);
			if (this.mapEvent.handle != null)
				GEvent.removeListener(this.mapEvent.handle);
			this.mapEvent.handle = GEvent.addListener(this.mapObj, "click", this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
		} else {
			this.setPaning(true);
			this.mapEvent.click = null;
			if (this.mapEvent.handle != null)
				GEvent.removeListener(this.mapEvent.handle);
			this.mapEvent.handle = null;
		}
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(mapObj, posObj) {
		if (this.mapEvent.click != null && posObj != null) {
			this.mapEvent.click(posObj.lat(), posObj.lng());
		}
	},
/**
 * 마크 설명문 보이기
 * @param {object} markerObj 마크 Object
 */
	showMarker : function(markerObj) {
		if (this.mapEvent.click != null)
			return ;
		var findidx = 0;
		var findMarker = null;
		var idx = 0;
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (markerObj == marker.obj) {
				findidx = i;
				findMarker = marker;
			}
		}
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			this.parentNode.showMarker(findidx, 
				point.lat(), point.lng(), findMarker.label, findMarker.markType, 
				findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
				findMarker.urlTxt, findMarker.urlType
			);
		}
	},
/**
 * 폴리 라인 그리기
 * @param {array} 폴리라인정보
 */
	showPolyline : function(polylineInfo) {
		if (this.lastpolylineObjs != null && this.lastpolylineObjs.length > 0) {
			for(var i = 0 ; i < this.lastpolylineObjs.length; i++) 
				this.mapObj.removeOverlay(this.lastpolylineObjs[i]);
		}
		this.lastpolylineObjs = [];
		if (polylineInfo != null) {
			for(var j = 0; j < polylineInfo.length ; j++) {
				var currObj = polylineInfo[j];
				var pointObj = [];
				for (var i = 0; i < currObj.lines.length;  i++) {
					var posObj = currObj.lines[i];
					pointObj.push(new GLatLng(posObj[1],posObj[0]));
				}
				var polylineObj = new GPolyline(pointObj,currObj.color ,currObj.weight);
				this.mapObj.addOverlay(polylineObj);
				this.lastpolylineObjs.push(polylineObj);
			}
		}
	},
/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {
		var findMarker = this.markers[idx];
		if (findMarker != null) {
			var point = findMarker.obj.getPoint();
			return {Lat : point.lat() , Lon : point.lng(), Label : findMarker.label, markType : findMarker.markType, 
				Icon : findMarker.icon, Color : findMarker.color, Extra : findMarker.extra, extraType : findMarker.extraType}
		} else
			return {};
	},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {
		this.parentNode.hideMarker();
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {int} markType 마크타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (markType > 0) 
			this.removeMarkerPos(lat,lon);
		if (typeof markColor == 'undefined')
			markColor = 0;
		if (typeof markIcon == 'undefined')
			markIcon = 0;
		if (typeof isEditable == 'undefined')
			isEditable = false;
		if (typeof extra == 'undefined')
			extra = '';
		var geoPoint = new GLatLng(lat, lon);
		var newicon = new GIcon(this.baseIcon);
		newicon.image = this.parentNode.getMarkerImg(markIcon);
		var newMarker= new GMarker(	geoPoint, {icon : newicon});
		if (isEditable || label != '' || urlTxt != '' || markType == 2)
			GEvent.addListener(newMarker, "mouseover", this.showMarker.bind(this,newMarker));
		this.mapObj.addOverlay(newMarker);
		var polylineObj = null;
		if (extra != '' && extratype == 'polyline') {
			polylineInfo = this.parentNode.getExtraPolyline(extra, 'WGS',2);
			var lineObj = [];
			for (var i = 0; i < polylineInfo.lines.length;  i++) {
				var posObj = polylineInfo.lines[i];
				lineObj.push(new GLatLng(posObj[0],posObj[1]));
			}
			var polylineObj = new GPolyline(lineObj,polylineInfo.color,this.parentNode.basePolyline.weight);
			this.mapObj.addOverlay(polylineObj);
		}
		this.markers.push({obj : newMarker, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : polylineObj, urlTxt : urlTxt, urlType : urlType});
		if (markType == 2)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];
			for(var idx = 0 ; idx < this.markers.length; idx ++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else
					newMarker.push(marker);
			}
			this.markers = newMarker;
			if (isPolyline)
				this.drawPolyline();
		} else
			findMarker = markerObj;
		if (addedObj != null)	
			this.mapObj.removeOverlay(addedObj);
		this.mapObj.removeOverlay(findMarker);
	},
/**
 * 위도 경도로 마크 삭제하기
 * @param {object} lat 위도
 * @param {object} lon 경도
 */
	removeMarkerPos : function(lat, lon) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var point = marker.obj.getPoint();
			if (point.lat() == lat && point.lng() == lon) 
				this.removeMarker(marker.obj, marker.addedObj);
			else
				newMarker.push(marker);
		}
		this.markers = newMarker;
	},
/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						marker.obj.hide();
						if (marker.addedObj != null)
							marker.addedObj.hide();
						marker.isHidden = true;
						newMarker.push(marker);
						break;
					case 2 :
						marker.obj.show();
						if (marker.addedObj != null)
							marker.addedObj.show();
						marker.isHidden = false;
						newMarker.push(marker);
						break;
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (markType == 2) {
			this.drawPolyline(markHidden);
			this.showPolyline();
		}
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			marker.obj.setLatLng(new GLatLng(pos[0],pos[1]));
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined')  {
			marker.icon = options.icon;
			marker.obj.setImage(this.parentNode.getMarkerImg(marker.icon));
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var Bound = this.mapObj.getBounds();
		this.parentNode.setBounds(Bound.getNorthEast().lat(), Bound.getSouthWest().lng(), Bound.getSouthWest().lat(), Bound.getNorthEast().lng());
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (typeof markTypes[marker.markType] != 'undefined' && markTypes[marker.markType] && !marker.isHidden) {
				var point = marker.obj.getPoint();
				if (marker.markType == 2 || this.parentNode.isInBounds(point.lat(), point.lng()))
					markerinfo.push([point.lat(), point.lng(), marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
			}
		}
		return markerinfo;
	},
/**
 * 폴리라인 다시 그리기
  * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {
		switch(markHidden) {
			case 1 : 
				if (	this.polylineObj != null) 
					this.polylineObj.hide();
				break;
			case 2 :
				if (	this.polylineObj != null) 
					this.polylineObj.show();
				break;
			default : 
				if (	this.polylineObj != null) {
					this.mapObj.removeOverlay(this.polylineObj);
					this.polylineObj = null;
				}
				var lineObj = [];
				var lastObj = null;
				var distance_killometers = 0;
				for(var i = 0 ; i < this.markers.length ; i++) {
					var marker = this.markers[i];
					if (marker.markType == 2) {
						var geoPoint = marker.obj.getPoint();
						if (lastObj != null) {
							distance_killometers += geoPoint.distanceFrom(lastObj);
							marker.extra = cafen.RMap.Conf.getDistanceString(distance_killometers);
						} else
							marker.extra = cafenMsg.get('map_0029');
						lineObj.push(geoPoint);
						lastObj = geoPoint;
					}
				}
				if (lineObj.length > 0) {
					this.polylineObj = new GPolyline(lineObj,this.parentNode.basePolyline.color ,this.parentNode.basePolyline.weight);
					this.mapObj.addOverlay(this.polylineObj);
				}
				break;
		}
	},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		return this.mapObj.convertXYLatLon(x,y);
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		return this.mapObj.convertLatLonXY(lat, lon);
	}
},cafen.RMap.NullMap.prototype);


/**
 * @class VEMap 맵
 * @constructor 
 * @param {cafen.RMap} parentNode 부모노드
 */
cafen.RMap.VEMap = function(parentNode) {
	this.initVEMap(parentNode);
};

cafen.RMap.VEMap.prototype = cafen.extendClass({
	isUnEditable : false,
	mapFunc : {world:true, sat : true, hyb : true},
	mapObj : null,
	markers : [],
	polylineObj : null,
	mapEvent : {click:null, clickbind : null},
	initVEMap : function(parentNode) {
		this.parentNode = parentNode;
		this.id = cafen.getUniqID('vemap');
		this.mapArea = new cafen.Div({attribute : {id : this.id}, style : {width : this.parentNode.getWidth()+'px', height : this.parentNode.getHeight() + 'px', overflow : 'hidden', overflowX :'hidden', overflowY :'hidden'}});
		this.parentNode.getObject().appendChild(this.mapArea);
		this.mapObj = new VEMap(this.id);
		this.mapObj.SetDashboardSize(VEDashboardSize.Small);
		this.mapObj.LoadMap(new VELatLong(this.parentNode.getLatitude(), this.parentNode.getLongitude(), 0, VEAltitudeMode.RelativeToGround), 10, VEMapStyle.Road, false, VEMapMode.Mode2D, false, 1);
		if (!this.parentNode.options.toolbaroff)
			this.mapObj.HideDashboard();
		else
			this.mapObj.ShowDashboard();
		this.setCenter(this.parentNode.getLatitude(), this.parentNode.getLongitude());
		this.setZoom(this.parentNode.getZoom());
		this.mapObj.AttachEvent("onmouseover", this.showMarker.bind(this));
		this.mapObj.AttachEvent("onstartpan", this.hideMarker.bind(this));
		this.mapEvent = {click : null, clickbind : this.getClickEvent.bind(this)};
		var basecolor = this.hex2rgb(this.parentNode.basePolyline.color);
		this.markerSizeObj = {size : new VEPixel(Math.round(this.parentNode.baseIconSize.width*(0)) , Math.round(this.parentNode.baseIconSize.height*(-0.4))) , coord : new VEPixel(0,0), color : new VEColor(basecolor.r,basecolor.g,basecolor.b,0.7)};
	},
	hex2rgb : function(hex) {
		if (hex != '') {
			if (m = hex.match(/#?([0-9a-f]{6})/i))
				m = m[1];
			m = m.match(/../g);
			return {
				r : Number("0x" + m[0]),
				g : Number("0x" + m[1]),
				b : Number("0x" + m[2])
			}
		} else {
			return {
				r : Number("0xff"),
				g : Number("0xff"),
				b : Number("0xff")
			}
		}
	},

/**
 * 중심설정
 * @param {float} lat 위도
 * @param {float} lon 경도
 * @param {boolean} pan 팬이동방식여부
 */
	setCenter : function(lat,lon, pan) {
		if (typeof pan != 'undefined' && pan) {
			this.mapObj.PanToLatLong(new VELatLong(lat,lon));
		}else {
			this.mapObj.SetCenter(new VELatLong(lat,lon));
		}
	},
/**
 * 줌레벨설정
 * @param {int} level 줌레벨
 * @param {int} move 이동레벨
 */
	setZoom : function(level, move) {
		if (typeof move == 'number' && move != 0) {
			if (move < 0) 
				this.mapObj.ZoomIn();
			else
				this.mapObj.ZoomOut();
		} else {
			level = (level == null) ? this.mapObj.GetZoomLevel() - 0: (level);
			if (typeof move == 'number' && move != 0) 
				level += move;
			if (level < 1) level = 1;
			else if (level > 19) level = 19;
			this.mapObj.SetZoomLevel(level);
		}
		
		
	},
/**
 * 맵타잎설정
 * @param {int} mapType 맵타잎
 */
	setMapType : function(mapType) {
		switch(mapType) {
			case 0 :
				this.mapObj.SetMapStyle( VEMapStyle.Road);
				break;
			case 1 :
				this.mapObj.SetMapStyle( VEMapStyle.Aerial);
				break;
			case 2 :
				this.mapObj.SetMapStyle( VEMapStyle.Hybrid);
				break;
		}	
	},
/**
 * 맵정보 가져오기
 * @return {array} 맵정보
 */
	getMapInfo : function() {
		var current_type = 0;
		var mapType = this.mapObj.GetMapStyle();
		switch(mapType) {
			case VEMapStyle.Road :
				current_type = 0;
				break;
			case VEMapStyle.Aerial :
				current_type = 1;
				this.mapObj.SetMapStyle( );
				break;
			case VEMapStyle.Hybrid :
				current_type = 2;
				break;
		}
		return {APIType : 'VEMap', Lat : this.mapObj.GetCenter().Latitude, Lon : this.mapObj.GetCenter().Longitude, Zoom : (this.mapObj.GetZoomLevel()), MapType : current_type};
	},
/**
 * 지동 이동 설정
 * @param {boolean} bl 지동 이동가능여부
 */
	setPaning : function(bl) {
		
	},
/**
 * 이벤트 설정
 * @param {function} clickEvent 클릭 이벤트
 */
	setEvent : function(clickEvent) {
		if (clickEvent != null && typeof clickEvent == 'function') {
			this.setPaning(false);
			if (this.mapEvent.click != null)
				this.mapObj.DetachEvent('onclick', this.mapEvent.clickbind);
			this.mapObj.AttachEvent("onclick", this.mapEvent.clickbind);
			this.mapEvent.click = clickEvent;
		} else {
			this.setPaning(true);
			if (this.mapEvent.click != null)
				this.mapObj.DetachEvent('onclick', this.mapEvent.clickbind);
			this.mapEvent.click = null;
			this.mapEvent.handle = null;
		}
	},	
/**
 * 클릭 이벤트 좌표 전달하기
 * @param {object} 이벤트 좌표
 */
	getClickEvent : function(event) {
		if (this.mapEvent.click != null && event != null) {
			var latlng = this.getXYLatLon(event.mapX, event.mapY);
			this.mapEvent.click(latlng[0], latlng[1]);
		}
	},
/**
 * 마크 설명문 보이기
 */
	showMarker : function(markerObj) {
		return ;
		if (this.mapEvent.click != null)
			return ;
		if (markerObj.elementID != null) {
			var findidx = 0;
			var findMarker = null;
			markerObj = this.mapObj.GetShapeByID(markerObj.elementID);
			for(var i = 0 ; i < this.markers.length ; i++) {
				var marker = this.markers[i];
				if (markerObj == marker.obj) {
					findidx = i;
					findMarker = marker;
				}
			}
			if (findMarker != null) {
				var point = findMarker.obj.GetPoints()[0];
				this.parentNode.showMarker(findidx, 
					point.Latitude, point.Longitude, findMarker.label, findMarker.markType, 
					findMarker.icon, findMarker.color, findMarker.isEditable, findMarker.extra, findMarker.extraType,
					findMarker.urlTxt, findMarker.urlType
				);
			}
		}
	},
/**
 * 폴리 라인 그리기
 * @param {array} 폴리라인정보
 */
	showPolyline : function(polylineInfo) {
		if (this.lastpolylineObjs != null && this.lastpolylineObjs.length > 0) {
			for(var i = 0 ; i < this.lastpolylineObjs.length; i++) 
				this.mapObj.DeleteShape(this.lastpolylineObjs[i]);
		}
		this.lastpolylineObjs = [];
		if (polylineInfo != null) {
			for(var j = 0; j < polylineInfo.length ; j++) {
				var currObj = polylineInfo[j];
				var pointObj = [];
				for (var i = 0; i < currObj.lines.length;  i++) {
					var posObj = currObj.lines[i];
					pointObj.push(new VELatLong(posObj[1],posObj[0]));
				}
				var polylineObj = new VEShape(VEShapeType.Polyline, pointObj);
				polylineObj.SetLineWidth(currObj.weight);
				var basecolor = this.hex2rgb(currObj.color);
				polylineObj.SetLineColor(new VEColor(basecolor.r,basecolor.g,basecolor.b,0.7));
				polylineObj.HideIcon();
				this.mapObj.AddShape(polylineObj);
				this.lastpolylineObjs.push(polylineObj);
			}
		}
	},
	/**
 * 마크 정보 가져오기
 * @param {int} 마크 번호
 * @return {object} 마크 정보
 */
	getMarkerInfo : function(idx) {
		var findMarker = this.markers[idx];
		if (findMarker != null) {
			var point = findMarker.obj.GetPoints()[0];
			return {Lat : point.Latitude, Lon : point.Longitude, Label : findMarker.label, markType : findMarker.markType, 
				Icon : findMarker.icon, Color : findMarker.color, Extra : findMarker.extra, extraType : findMarker.extraType}
		} else
			return {};
	},
/**
 * 마크 설명문 숨기기
 */
	hideMarker : function() {
		this.parentNode.hideMarker();
	},
/**
 * 마크 추가하기
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @param {string} label 라벨
 * @param {int} markType 마크타잎
 * @param {int} markIcon 아이콘 번호
 * @param {int} markColor 색상번호 번호
 * @param {string} extra 마크 기타정보
 * @param {string} extratype 마크 기타정보 형태
 */
	addMarker : function(lat,lon,label, markType, markIcon, markColor, isEditable, extra, extratype, urlTxt, urlType) {
		if (markType > 0) 
			this.removeMarkerPos(lat,lon);
		if (typeof markColor == 'undefined')
			markColor = 0;
		if (typeof markIcon == 'undefined')
			markIcon = 0;
		if (typeof isEditable == 'undefined')
			isEditable = false;
		if (typeof extra == 'undefined')
			extra = '';
		var vePoint = new VELatLong(lat, lon);
		var newMarker = new VEShape(VEShapeType.Pushpin, vePoint);
		var icon = new VECustomIconSpecification();
		icon.ImageOffset = this.markerSizeObj.size;
		icon.TextContent = "&nbsp;";   
		icon.TextSize = 1;   
		icon.TextOffset = this.markerSizeObj.coord;
		icon.Image = this.parentNode.getMarkerImg(markIcon);
		newMarker.SetCustomIcon(icon);
		this.mapObj.AddShape(newMarker);
		var polylineObj = null;
		if (extra != '' && extratype == 'polyline') {
			polylineInfo = this.parentNode.getExtraPolyline(extra, 'WGS',5);
			var lineObj = [];
			for (var i = 0; i < polylineInfo.lines.length;  i++) {
				var posObj = polylineInfo.lines[i];
				lineObj.push(new VELatLong(posObj[0],posObj[1]));
			}
			var polylineObj = new VEShape(VEShapeType.Polyline, lineObj);
			polylineObj.SetLineWidth(currObj.weight);
			var basecolor = this.hex2rgb(currObj.color);
			polylineObj.SetLineColor(new VEColor(basecolor.r,basecolor.g,basecolor.b,0.7));
			polylineObj.HideIcon();
			this.mapObj.AddShape(polylineObj);
		}
		this.markers.push({obj : newMarker, label : label , color : markColor, icon : markIcon , markType : markType, extra : extra , isEditable : isEditable, isHidden : false, extraType : extratype, addedObj : polylineObj, urlTxt : urlTxt, urlType : urlType});
		if (markType == 2)
			this.drawPolyline();
	},
/**
 * 마크 삭제하기
 * @param {object} maker 삭제할 마크
 */
	removeMarker : function(markerObj, addedObj) {
		var findMarker = null;
		if (typeof markerObj != 'object') {
			var isPolyline = false;
			var newMarker = [];
			for(var idx = 0; idx < this.markers.length; idx++) {
				var marker = this.markers[idx];
				if (idx == markerObj) {
					if (marker.markType == 2)
						isPolyline = true;
					findMarker = marker.obj;
					addedObj = marker.addedObj;
				} else 
					newMarker.push(marker);
			}
			this.markers = newMarker;
			if (isPolyline)
				this.drawPolyline();
		} else
			findMarker = markerObj;
		if (addedObj != null)
			this.mapObj.DeleteShape(addedObj);
		this.mapObj.DeleteShape(findMarker);
	},
/**
 * 위도 경도로 마크 삭제하기
 * @param {object} lat 위도
 * @param {object} lon 경도
 */
	removeMarkerPos : function(lat, lon) {
		var removeFnc = this.removeMarker.bind(this);
		var newMarker = [];
		for(var i = 0; i < this.markers.length; i++) {
			var marker = this.markers[i];
			var point = marker.obj.GetPoints()[0];
			if (point.Latitude == lat && point.Longitude == lon) {
				this.removeMarker(marker.obj, marker.addedObj);
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
	},
	/**
 * 마크 삭제하기
 * @param {int} markType 지울 마크 타잎
 * @param {boolean} markHidden 마크 숨기기
 */
	removeAllMarker : function(markType, markHidden) {
		var removeFnc = this.removeMarker.bind(this);
		var newMarker = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (marker.markType == markType) {
				switch(markHidden) {
					case 1 :
						marker.obj.Hide();
						if (marker.addedObj != null)
							marker.addedObj.Hide();
						marker.isHidden = true;
						newMarker.push(marker);
						break;
					case 2 :
						marker.obj.Show();
						if (marker.addedObj != null) 
							marker.addedObj.Show();
						marker.isHidden = false;
						newMarker.push(marker);
						break;
					default :
						this.removeMarker(marker.obj, marker.addedObj);
						break;
				}
			} else
				newMarker.push(marker);
		}
		this.markers = newMarker;
		if (markType == 2) {
			this.drawPolyline(markHidden);
			this.showPolyline();
		}
	},
/**
 * 마크 정보 변경
 * @param {int} seqn 마크 고유번호
 * @param {object} options 마크 옵션
 */
	modifyMarker : function(seqn, options) {
		var marker = this.markers[seqn];
		if (typeof options.x != 'undefined' && typeof options.y != 'undefined') {
			var pos = this.getXYLatLon(options.x, options.y);
			marker.obj.SetPoints([new VELatLong(pos[0],pos[1])]);
			if (marker.markType == 2)
				this.drawPolyline();
		}
		if (typeof options.icon != 'undefined' && options.icon != marker.icon)  {
			var icon = new VECustomIconSpecification();
			icon.Image = this.parentNode.getMarkerImg(options.icon);
			icon.ImageOffset = this.markerSizeObj.size;
			icon.TextContent = "&nbsp;";   
			icon.TextSize = 1;   
			icon.TextOffset = this.markerSizeObj.coord;
			marker.obj.SetCustomIcon(icon);
		}
		if (typeof options.color != 'undefined')  
			marker.color = options.color;
		if (typeof options.label != 'undefined')  
			marker.label = options.label;
		if (typeof options.urlTxt != 'undefined')  
			marker.urlTxt = options.urlTxt;
		if (typeof options.urlType != 'undefined')  
			marker.urlType = options.urlType;
	},
/**
 * 마크 정보 가져오기
 * @param {array} markTypes 가져올 마크타잎
 * @return {array} 마크 정보
 */
	getMarker : function(markTypes) {
		var BoundLeftTop = this.getXYLatLon(0,0);
		var BoundRightBottom = this.getXYLatLon(this.parentNode.getWidth(),this.parentNode.getHeight());
		this.parentNode.setBounds(BoundLeftTop[1], BoundLeftTop[0], BoundRightBottom[0], BoundRightBottom[1]);
		var markerinfo = [];
		for(var i = 0 ; i < this.markers.length ; i++) {
			var marker = this.markers[i];
			if (typeof markTypes[marker.markType] != 'undefined' && markTypes[marker.markType] && !marker.isHidden) {
				var point = marker.obj.GetPoints()[0];
				if (marker.markType == 2 || this.parentNode.isInBounds(point.Latitude, point.Longitude))
					markerinfo.push([point.Latitude, point.Longitude, marker.markType, marker.label, marker.icon, marker.color, marker.isEditable, marker.extra, marker.extraType , marker.urlTxt, marker.urlType]);
			}
		}
		return markerinfo;
	},
/**
 * 폴리라인 다시 그리기
 * @param {int} markHidden 0삭제/1숨기기/2보이기
 */
	drawPolyline : function(markHidden) {
		switch(markHidden) {
			case 1 : 
				if (this.polylineObj != null) 
					this.polylineObj.Hide();
				break;
			case 2 :
				if (this.polylineObj != null) 
					this.polylineObj.Show();
				break;
			default : 
				if (this.polylineObj != null) {
					this.mapObj.DeleteShape(this.polylineObj);
					this.polylineObj = null;
				}
				var lineObj = [];
				var lastObj = null;
				var distance_killometers = 0;
				for(var i = 0 ; i < this.markers.length ; i++) {
					var marker = this.markers[i];
					if (marker.markType == 2) {
						var geoPoint = marker.obj.GetPoints()[0];
						if (lastObj != null) {
							distance_killometers += cafen.RMap.Conf.getDistance(lastObj,geoPoint);
							marker.extra = cafen.RMap.Conf.getDistanceString(distance_killometers);
						} else
							marker.extra = cafenMsg.get('map_0029');
						lineObj.push(geoPoint);
						lastObj = geoPoint;
					}
				}
				if (lineObj.length > 1) {
					this.polylineObj = new VEShape(VEShapeType.Polyline, lineObj);
					this.polylineObj.SetLineWidth(this.parentNode.basePolyline.weight);
					var basecolor = this.hex2rgb(this.parentNode.basePolyline.color);
					this.polylineObj.SetLineColor(new VEColor(basecolor.r,basecolor.g,basecolor.b,0.7));
					this.polylineObj.HideIcon();
					this.mapObj.AddShape(this.polylineObj);
				}
				break;
		}
	},
/**
 * XY 좌표을 Lat Lon 좌표로 변환
 * @param {number} x X 좌표
 * @param {number} y Y 좌표
 * @return  {array} [lat, lon] 좌표
 */
	getXYLatLon : function(x,y) {
		var latlng = this.mapObj.PixelToLatLong(new VEPixel(x,y));
		return [latlng.Latitude,latlng.Longitude];
	},
/**
 * Lat Lon 좌표을 X Y 좌표로 변환
 * @param {number} lat 위도
 * @param {number} lon 경도
 * @return  {array} [x,y] 좌표
 */
	getLatLonXY : function(lat, lon) {
		var pixel = this.mapObj.LatLongToPixel(new VELatLong(lat,lon));
		return [pixel.x,pixel.y];
	}
},cafen.RMap.NullMap.prototype);


var cafenMap_HTC = new cafenMap();

cafen.checkLoad();

