function AppMain(oMap)
{
    var oOwner  = this;
    var oPinGroup   = null;
    var oMoveCursor = null;
    var oPopup  = null;

    var nStartTick = 0;
    var bSignal = false;
    var nStopCheckInterval = 500;

    var c_spot_id = 0;

    // 移動可能カーソル生成
    oMoveCursor = new CMovableCursor( oMap );

    var _OnChangedPosition = oMap.OnChangedPosition;
    oMap.OnChangedPosition = function (nLongitude, nLatitude) {
        nStartTick = GetTick();
        bSignal = false;
        oPinGroup && oPinGroup.Reset();
        oMoveCursor.OnChangedPosition(nLongitude, nLatitude);
        if (_OnChangedPosition) { _OnChangedPosition(nLongitude, nLatitude); }
    }

    var _OnChangedScale = oMap.OnChangedScale;
    oMap.OnChangedScale = function( nScale ) {
        nStartTick = GetTick();
        bSignal = false;
        oPinGroup && oPinGroup.Reset();
        oMoveCursor.OnChangedScale( nScale );
        if (_OnChangedScale) { _OnChangedScale(nScale); }
    }

    var _OnDraw = oMap.OnDraw;
    oMap.OnDraw = function() {
        oPinGroup && oPinGroup.Draw(oMap);
        if (oPopup) {
            var oRet = oMap.GetViewPoint(
                oPopup.oContents.Longitude,
                oPopup.oContents.Latitude
            );
            oPopup.Draw( oRet.PixelX + 8, oRet.PixelY - 26 );
        }
        oMoveCursor.OnDraw();
        if (! bSignal) {
	        var lCurrTick = GetTick()
	        if (lCurrTick - nStartTick > nStopCheckInterval) {
	            var oLeftTop = oMap.GetMapPoint(0, 0);
	            var oRightBottom = oMap.GetMapPoint(CMN_GetWindowWidth(oMap.window), CMN_GetWindowHeight(oMap.window));
	            getSpots(oLeftTop.Longitude, oLeftTop.Latitude, oRightBottom.Longitude, oRightBottom.Latitude);
	            bSignal = true;
	        }
	    }
        if (_OnDraw) { _OnDraw(); }
    }

    function GetTick() {
        var d = new Date();
        return eval(d/1);
    }

    oMap.OnResizeView = function() {
        oPinGroup && oPinGroup.Reset();
    }

    // アプリ内連携処理
    function ShowPopupAndMoveToSpot(uid) {
        var oCustomPop = null;
        if (oPopup) {
            if (oPopup.uid == uid) {
                oCustomPop = oPopup;
            } else {
                oPopup.Remove();
                oPopup = null;
            }
        }

        if( oCustomPop == null ) {
            var oCustomPop = CreateCustomPop( oMap.document, oInnerList.Find( uid ) );
            oCustomPop.uid = uid;   
            oCustomPop.OnClosePopup = function() {
                if ( oPopup == this ) { oPopup = null; }
            } 
            oCustomPop.OnClickContent = function() {
                ActivatePop( this );
            }
            oCustomPop.OnLoadContents = function() {
                FitToPopPos( this );
                ActivatePop( this );
            }
            oPopup = oCustomPop;
        } else {
            FitToPopPos( oCustomPop );
            ActivatePop( oCustomPop );
        }
    }

    function ActivatePop( oCustomPop ) {
        oPopup.zIndexBase = 20;
    }

    function FitToPopPos( oCustomPop ) {
        oMoveCursor.oTrueTargPos.Longitude = oCustomPop.oContents.Longitude;
        oMoveCursor.oTrueTargPos.Latitude = oCustomPop.oContents.Latitude;

        var oPixelDst = oMap.GetViewPoint(
            oMoveCursor.oTrueTargPos.Longitude,
            oMoveCursor.oTrueTargPos.Latitude
        );
        var oOffset = oCustomPop.CalcMoveOffset(
            oPixelDst,
            CMN_GetWindowWidth( oMap.window ),
            CMN_GetWindowHeight( oMap.window )
        );

        var oPixelSrc = oMap.GetViewPoint(oMap.Longitude, oMap.Latitude);
        oMoveCursor.oVirtualTargPos = oMap.GetMapPoint(
            oPixelSrc.PixelX + oOffset.MoveX,
            oPixelSrc.PixelY + oOffset.MoveY
        );

//      oMap.Longitude--;

        oMap.Scroll( oMoveCursor.oVirtualTargPos.Longitude, oMoveCursor.oVirtualTargPos.Latitude );
    }

    function getSpots(left, top, right, bottom) {

        jQuery.ajax({
            'type': 'GET',
            'url': window.location.href.replace(/\/\?.*$/, '') + '/spots.php',
            'data': {left: left, right: right, top: top, bottom: bottom, c_spot_id: oOwner.c_spot_id},
            'success': putSpots,
            'failure': function() { alert('error.'); }
        });
    }
    function putSpots(res) {

        // 内部用地点リストの作成
        oInnerList = eval(res);
// auto zoom down
//      if (oInnerList.length == 0) { oMap.Scale++; return; }
        oInnerList.Find = function( uid ) {

            for ( var i = 0; i < this.length; i++) {
                if( this[i].uid == uid ) { return this[i]; }
            }
            return null;
        }
        if (oPinGroup) { oPinGroup.Destroy(); }

        // ピン管理の初期化
        oPinGroup = new CPinGroup( oMap, oInnerList );
        oPinGroup.OnMouseOver = function( uid ) {}
        oPinGroup.OnMouseOut = function( uid ) {}
        oPinGroup.OnMouseDown = function( uid ) {}
        oPinGroup.OnMouseUp = function( uid ) { ShowPopupAndMoveToSpot( uid ) }
    }
    nStartTick = GetTick();

    return  this;
}
