/** Defines the Wales_PointOfInterest_Controller class.
 *
 * @author Josh Zerin <josh.zerin@standingdog.com>
 * @since Thursday, April 16, 2009
 *
 * @package HotelWales
 * @subpackage Library
 */

/** Controller for interacting with points on a GMap.
 *
 * @package PointOfInterest
 */
function Wales_PointOfInterest_Controller(  )
{
  /**#@+ @access private */
  var

    /** Unique identifier for this object.
     *
     * @var Number
     */
    $myUID = Wales_PointOfInterest_Controller.generateUID(),

    /** The map that this controller controls.
     *
     * @var google.maps.Map2
     */
    $myMap;
  /**#@-*/

  /** Accessor for $myUID.
   *
   * @return Number
   */
  this['getUID'] =
    function(  )
    {
      return $myUID;
    };

  /** Accessor for $myMap.
   *
   * @return google.maps.Map2
   */
  this['getMap'] =
    function(  )
    {
      return $myMap;
    };

  /** Modifier for $myMap.
   *
   * @param google.maps.Map2 $Map
   *
   * @return Wales_Controller this (for chaining).
   */
  this['setMap'] =
    function( $Map )
    {
      /* Verifying the constructor for $Map is unreliable, so we'll just have to
       *  trust the script for now.
       */
      $myMap = $Map;
      return this;
    };

  /** Toggles pins for points of interest.
   *
   * @param Wales_PointOfInterest|Wales_PointOfInterest_Category $poi
   * @param Boolean $force
   *  - undefined:  Toggle pin state.
   *  - true:       Force pin active.
   *  - false:      Force pin inactive.
   *
   * @return Boolean Returns the end state of the pin(s).  This is useful when
   *  using togglePins() in event handlers.
   */
  this['togglePins'] =
    function( $poi, $force )
    {
      /* Validate $myMap. */
      if( typeof($myMap) == 'undefined' )
      {
        throw 'togglePins() called, but no map has been assigned to the controller yet.';
      }

      /* Set a default value for $state. */
      if( typeof($force) == 'undefined' )
      {
        $state = null;
      }
      else
      {
        $state = Boolean($force);
      }

      switch( $poi.constructor )
      {
        /* When a category is passed in:
         *
         * - Change the active category if necessary.
         * - Toggle all pins in the category uniformly:
         *   - If at least 1 pin is hidden, show all.
         *   - If all pins are visible, hide all.
         */
        case Wales_PointOfInterest_Category:

          /* Determine how to set pin state:
           *
           * If $force is set, then use $force.  Otherwise, set all pins visible
           *  unless they're all visible.
           */
          if( $state === null )
          {
            $state = false;
            for( var $uid in $poi.getPointsOfInterest() )
            {
              if( ! $poi.getPointsOfInterest()[$uid].getPin().getState() )
              {
                $state = true;
                break;
              }
            }
          }

          /* Set pin visibility. */
          for( var $uid in $poi.getPointsOfInterest() )
          {
            $poi.getPointsOfInterest()[$uid].getPin()
              .setMap($myMap)
              .setState($state);
          }

          /* Recenter the map. */
          this.recenterMap();
        break;

        /* When an individual point is passed in:
         *
         * - Change the active category if necessary.
         * - Toggle the pin.
         */
        case Wales_PointOfInterest:

          /* Determine how to set pin state:
           *
           * If $force is set, then use $force.  Otherwise, toggle pin state.
           */
          if( $state === null )
          {
            $state = ! $poi.getPin().getState();
          }

          /* Set pin visibility. */
          $poi.getPin()
            .setMap($myMap)
            .setState($state);

          /* Recenter the map. */
          this.recenterMap($state ? $poi.getPin() : false);
        break;

        default:
          throw 'Unknown argument passed to togglePins().';
        break;
      }

      return $state;
    };

  /** Re-centers the map around a pushpin.
   *
   * @param Wales_PointOfInterest_Pin $Pin If set, recenter around this pin.  If
   *  not set, recenter around the hotel's pushpin.
   *
   * @return Wales_PointOfInterest_Controller this (for chaining).
   */
  this['recenterMap'] =
    function( $Pin )
    {
      if( $Pin && $Pin.constructor == Wales_PointOfInterest_Pin )
      {
        $myMap.panTo($Pin.getLatLng());
      }
      else
      {
        $myMap.panTo($youAreHere);
      }

      return this;
    };
}

/** The default zoom level for the map.
 *
 * @var Number
 */
Wales_PointOfInterest_Controller.defaultZoom = 13;

/** Generates a UID for a POI.
 *
 * @return Number
 */
Wales_PointOfInterest_Controller._UID = 0;
Wales_PointOfInterest_Controller.generateUID = function(  )
{
  return Wales_PointOfInterest_Controller._UID += 1;
}