
var gViewport = function(){

  var MAP_VIEWPORT_ID = "mapViewport";
  
	var _elMapViewport = null;
  var _elMiniMapPanel = null;
  var _oMapSelect = null;

  var _oMap = null;
  
  // *****************************************************
  //                   STATE MANAGEMENT
  // *****************************************************

  var STATE_UNINITALIZED = "UNINITALIZED";
  var STATE_NORMAL = "NORMAL";
  var STATE_MOUSEDOWN = "MOUSEDOWN";
  var STATE_DRAGGING_MAP = "DRAGGING_MAP";
  var STATE_SELECTING = "SELECTING";
  var STATE_RESIZING_MAP_SELECTION = "RESIZING_MAP_SELECTION";

  var _linkToImageActive = false;

  
  var _state = STATE_UNINITALIZED;

  // save the size of the viewport to help prevent false resize events 
  var _lastResizeViewportWidth = null;
  var _lastResizeViewportHeight = null;

  function _switchState( nextState ){
    _state = nextState;
  };

  function _isResizingSelector(){
    return _oMapSelect.isResizing();
  };


  // *****************************************************
  //                STATE MANAGEMENT END
  // *****************************************************


	function init(){
		_elMapViewport = $( MAP_VIEWPORT_ID );
    _oMap = gMap;
    _oMapSelect = gMapSelect;

		_registerEvents();
    _setViewportPositionAndSize();

    _oMap.init();
    _oMapSelect.init();

		
    _switchState( STATE_NORMAL );

    if( gIsMozilla ){
      _elMapViewport.style.cursor = "-moz-grab";
    } else if( gIsIE ){
      _elMapViewport.style.cursor = "url(/img/bn/openhand.cur)";
    } else {
      _elMapViewport.style.cursor = "hand";
    }
	};
	 

	function windowResize( e ){

    YAHOO.log("windowResize called");

    //$$$$$ only call resize if the window size has changes significantly from last time
    _performWindowResize();

    if( e ){
      YUE.stopPropagation( e );
    }
	};



  function _performWindowResize(){
    // resizes the map viewport based on the window size and triggers the map to redraw

    _setViewportPositionAndSize();

    _oMap.resize();
  };

  function _setViewportPositionAndSize(){
		// set viewport size based on the browser window dimensions

    var clientWidth = YUD.getViewportWidth();
    var clientHeight = YUD.getViewportHeight();

    // compute and set the viewport size
		var viewportWidth = clientWidth - 275;
		var viewportHeight = YUD.getViewportHeight() - 120;    // -footer height - header height

		YUD.setStyle( _elMapViewport, "width", viewportWidth + "px" );
		YUD.setStyle( _elMapViewport, "height", viewportHeight + "px" );
    
    // place the minimap
    var elMiniMapPanel = $("miniMapPanel");

    var newTop = viewportHeight - 202;
    elMiniMapPanel.style.top = newTop + "px";
    
    //     var padLeft = parseInt( elMiniMapPanel.style.paddingLeft );
    //     var miniMapPanelWidth = elMiniMapPanel.clientWidth + padLeft + 2;
    //     var newLeft = viewportWidth - miniMapPanelWidth;
    //     elMiniMapPanel.style.left = newLeft + "px";
    
    elMiniMapPanel.style.visibility = "visible";
  };



  function getSize(){
    var width = parseInt( YUD.getStyle( _elMapViewport, "width" ) );
    var height = parseInt( YUD.getStyle( _elMapViewport, "height" ) );
    
    return [width, height];
  };


  function _setViewportCursorStyle( cursorStyle ){
    _elMapViewport.style.cursor = cursorStyle;
  };


  function _registerEvents(){

		// document events

    // I noticed that when the MiniMap constructor reads the clientWidth and clientHeight properties, it causes
    // a resize event in IE.  If I re-enable resize, I need to delay adding the resize handler as long as possible.
    YUE.addListener( window, "resize", windowResize, gViewport );

    // viewport events
    YUE.addListener( _elMapViewport, "mousedown", _viewportMouseDown );
    YUE.addListener( _elMapViewport, "mouseup", _viewportMouseUp );
    YUE.addListener( _elMapViewport, "mousemove", _viewportMouseMove );

	};



  // ********************
  //    EVENT HANDLERS
  // ********************

  function _viewportMouseDown( e, obj ) {

    switch( _state )
    {
    case STATE_NORMAL:

      // removing the alt key feature for now
//       // if the alt key is down and the map is at zoom zero start map selection 
//       if( e.altKey ) {
//         _startMapSelectArea( e );
//         YUE.stopEvent( e );
//         return;
//       } else {

//         // make sure mouse moves by _dragThresholdPixels
//         _switchState( STATE_MOUSEDOWN );
//         YUE.preventDefault( e );
//       }

      // make sure mouse moves by _dragThresholdPixels
      _switchState( STATE_MOUSEDOWN );
      YUE.preventDefault( e );

      break;
    }

  };



  function _viewportMouseMove( e, obj ) {
    switch( _state )
    {
    case STATE_MOUSEDOWN:
      _startMapDrag( e );
      _switchState( STATE_DRAGGING_MAP );
      break;

//     case STATE_DRAGGING_MAP:
//       _whileMapDrag( e );
// 			YUE.preventDefault( e );
//       break;

    case STATE_SELECTING:
      _whileMapSelectArea( e );
      break;
    }
  };

  function _viewportMouseUp( e, obj ) {

    switch( _state )
    {
    case STATE_MOUSEDOWN:
      _mapClick( e );
      break;
    case STATE_SELECTING:
      _endMapSelectArea( e );
      break;
    case STATE_DRAGGING_MAP:
      endMapDrag( e );
      break;
    case STATE_RESIZING_MAP_SELECTION:
      endMapSelectResize( e );
      break;
    }

  };

  function _viewportMouseOut( e, obj ) {
    switch( _state )
    {
    case STATE_DRAGGING_MAP:
      endMapDrag( e );
      break;
    }
  };

  // ************************
  //    END EVENT HANDLERS
  // ************************



  // *************
  //    ACTIONS
  // *************

  function startLinkToImage(e){
    _linkToImageActive = true;
    _setViewportCursorStyle("crosshair");
  };


  function endLinkToImage(e){
    _linkToImageActive = false;
    _setViewportCursorStyle("default");    
  }




  function _startMapDrag( e ){
    //    YAHOO.log( "start map drag" );
		_oMap.startMapDrag( e );
		_switchState( STATE_DRAGGING_MAP );
		gApp.hideLinkUI();  


    // attaching the drag listeners to the document so that the map continues to drag if the mouse leaves the viewport
    YUE.addListener(document,"mousemove", gMap.whileMapDrag, gMap, true);
    YUE.addListener(document,"mouseup", gViewport.endMapDrag, gViewport, true);

  };


  function endMapDrag( e ){
    //    YAHOO.log( "end map drag" );
    YUE.removeListener(document,"mousemove", gMap.whileMapDrag);
    YUE.removeListener(document,"mouseup", gViewport.endMapDrag);

    _oMap.endMapDrag( e );
    _switchState( STATE_NORMAL );
  };


  
  function _startMapSelectArea( e ){
    YAHOO.log( "start map select drag" );
    
    if( _oMap.getZoomLevel() == 0 ){
      _switchState( STATE_SELECTING );
      _oMapSelect.startSelectArea( e );
    } else {
      alert( "Please zoom in to zoom level 0 to make a selection." );
    }
  };
  function _whileMapSelectArea( e ){
    //    YAHOO.log( "while map select drag" );
    _oMapSelect.whileSelectArea( e );
  };
  function _endMapSelectArea( e ){
    YAHOO.log( "end map select drag" );
    _oMapSelect.endSelectArea( e );
    _switchState( STATE_NORMAL );
  };


  function startMapSelectResize(){
    YAHOO.log( "start map select resize" );

    var mapSelectCursor = _oMapSelect.getCursorValue();
    _setViewportCursorStyle( mapSelectCursor );
    
    _switchState( STATE_RESIZING_MAP_SELECTION );
  };

  function endMapSelectResize( e ){
    YAHOO.log( "end map select resize" );

    if( _state == STATE_RESIZING_MAP_SELECTION ){
      _oMapSelect.endResizing( e );
      _setViewportCursorStyle( "default" );
      _switchState( STATE_NORMAL );
    }
  };

  function _mapClick( e ){
    
		YAHOO.log( "map click" );
    _switchState( STATE_NORMAL );

    if( _linkToImageActive ){
      gApp.getLinkToImage(e);
      endLinkToImage();
    } else {
			if( !gMapSelect.isSelected() ){
				_oMap.mapClick( e );
			} 
		}

  };

  // *****************
  //    END ACTIONS 
  // *****************





	return { 
  init:init,
         windowResize:windowResize,
         getSize:getSize,
         startMapSelectResize : startMapSelectResize,
         endMapSelectResize : endMapSelectResize,
         endMapDrag : endMapDrag,
         startLinkToImage : startLinkToImage,
			endLinkToImage : endLinkToImage
         };
  
}();
