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

/** Models a local attraction for display on a GMap view.
 *
 * @package PointOfInterest
 */
function Wales_PointOfInterest(  )
{
  /**#@+ @access private */
  var

    /** A unique identifier for this POI.
     *
     * @var Number
     */
    $myUID = Wales_PointOfInterest_Controller.generateUID(),
  
    /** The parent category for this point of interest.
     *
     * @var Wales_PointOfInterest_Category
     */
    $myCategory,

    /** The pin that represents this POI on the map.
     *
     * @var Wales_PointOfInterest_Pin
     */
    $myPin,

    /** Link to the toggle link for this POI's pin.
     *
     * @var jQuery
     */
    $myLink,

    /** The name of the venue.
     *
     * @var String
     */
    $myName,

    /** The address of the venue.
     *
     * @var String
     */
    $myAddress,

    /** Website URL for the venue.
     *
     * @var String
     */
    $myURL,

    /** The latitude and longitude of the venue.
     *
     * @var Array [Number $latitude, Number $longitude]
     */
    $myGeocode;
  /**#@-*/

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

  /** Accessor for $myCategory.
   *
   * @return Wales_PointOfInterest_Category
   */
  this['getCategory'] =
    function(  )
    {
      return $myCategory;
    };

  /** Modifier for $myCategory.
   *
   * @param Wales_PointOfInterest_Category $Category
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setCategory'] =
    function( $Category )
    {
      if( $Category && $Category.constructor == Wales_PointOfInterest_Category )
      {
        $myCategory = $Category;

        /* Fix reciprocal reference if necessary. */
        if( ! $myCategory.getPointOfInterest(this) )
        {
          $myCategory.attach(this);
        }

        return this;
      }
      else
      {
        throw 'Category must be an instance of Wales_PointOfInterest_Category.';
      }
    };

  /** Accessor for $myPin.
   *
   * @return Wales_PointOfInterest_Pin Always returns a pin.  If the POI has not
   *  yet been assigned a pin, a new one will be created.
   */
  this['getPin'] =
    function(  )
    {
      if( ! $myPin )
      {
        this.setPin(new Wales_PointOfInterest_Pin());
      }

      return $myPin;
    };

  /** Modifier for $myPin.
   *
   * @param Wales_PointOfInterest_Pin $Pin
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setPin'] =
    function( $Pin )
    {
      /* Validate $Pin. */
      if( $Pin && $Pin.constructor == Wales_PointOfInterest_Pin )
      {
        $myPin = $Pin;

        /* Fix reciprocal reference if necessary. */
        if( $myPin.getPointOfInterest() != this )
        {
          $myPin.setPointOfInterest(this);
        }

        return this;
      }
      else
      {
        throw 'Pin must be an instance of Wales_PointOfInterest_Pin.';
      }
    };

  /** Returns the link for this POI.  Note:  might not be attached to the DOM
   *   yet.
   *
   * @param Boolean $createIfNotSet
   *
   * @return jQuery
   */
  this['getLink'] =
    function(  )
    {
      if( typeof($myLink) == 'undefined' )
      {
        /* Make this accessible to callbacks. */
        var $this = this;

        /* Create the link. */
        $myLink =
          $(document.createElement('a'))
            .attr('href', '#')
            .text(this.getName())
            .click( function(  ) {
              $(this).toggleClass(
                'poi-selected',
                $MapController.togglePins($this)
              );

              return false;
            });
      }

      return $myLink;
    };

  /** Accessor for $myName.
   *
   * @return String
   */
  this['getName'] =
    function(  )
    {
      return $myName;
    };

  /** Modifier for $myName.
   *
   * @param String $name
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setName'] =
    function( $name )
    {
      $myName = String($name);
      this.getPin().rebuildMarker();
      return this;
    };

  /** Accessor for $myAddress.
   *
   * @return String
   */
  this['getAddress'] =
    function(  )
    {
      return $myAddress;
    };

  /** Modifier for $myAddress.
   *
   * @param String $addy
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setAddress'] =
    function( $addy )
    {
      $myAddress = String($addy);
      this.getPin().rebuildMarker();
      return this;
    };

  /** Accessor for $myURL.
   *
   * @return String
   */
  this['getURL'] =
    function(  )
    {
      return $myURL;
    };

  /** Modifier for $myURL.
   *
   * @param String $URL
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setURL'] =
    function( $URL )
    {
      $myURL = String($URL);
      this.getPin().rebuildMarker();
      return this;
    };

  /** Accessor for $myGeocode.
   *
   * @return Array [Number $latitude, Number $longitude]
   */
  this['getGeocode'] =
    function(  )
    {
      return $myGeocode;
    };

  /** Modifier for $myGeocode.
   *
   * @param Array $geocode [Number $latitude, Number $longitude]
   *
   * @return Wales_PointOfInterest this (for chaining).
   */
  this['setGeocode'] =
    function( $geocode )
    {
      if( $geocode && $geocode.constructor == Array )
      {
        if( $geocode.length == 2 )
        {
          $lat = parseFloat($geocode[0]);
          $lon = parseFloat($geocode[1]);

          if( ! (isNaN($lat) || isNaN($lon)) )
          {
            $myGeocode = [$lat, $lon];
            this.getPin().rebuildMarker();
            return this;
          }
        }
      }

      throw 'Geocode must be an array with two Number elements.';
    };
}