/*------------------------------------------------------------------------------

   Copyright (c) 2005 Tyrell Corporation.

    This file is part of the Locative Blog project.
    http://locblog.sourceforge.net/

   Author   : $Author: darkeye $
   Version  : $Revision: 1.1 $
   Location : $Source: /cvsroot/locblog/website/var/htdocs/rotatingGlobe/sample/GeoLocation.js,v $

   Abstract : 

    A class representing a geogpraphical location.

   Copyright notice:

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License  
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
   
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
    GNU General Public License for more details.
   
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

------------------------------------------------------------------------------*/

/**
 *  Constructor for a geographic location, with a link.
 *
 *  @param id the id of the location (no spaces, etc.)
 *  @param name the name of the location
 *  @param longitude the longitude coordinate of the location
 *  @param latitude the latitude coordinate of the location
 *  @param url the url for more info on the location
 */
function GeoLocation(id,
                     name,
                     longitude,
                     latitude,
                     url)
{
    // the id of the location
    this.id = id;

    // the name of the location
    this.name = name;

    // the longitude coordinate of the location
    this.longitude = longitude < 0 ? 360 + longitude : longitude;

    // the latitude coordinate of the location
    this.latitude = latitude;

    // the url for more info on the location
    this.url = url;

    // the image used to mark the location visually
    this.markerImage = 'globeImages/5x5.png';

    // the width of the marker image
    this.markerWidth = 5;

    // the height of the marker image
    this.markerHeight = 5;

    // the x coordinate of this location, relative to the page window
    this.x = 0;

    // the y coordinate of this location, relative to the page window
    this.y = 0;

    // create the CSS definition for this location
    this.styleDefinition = geoLocationStyleDefinition;

    // create the HTML element source for this location
    this.htmlDefinition = geoLocationHtmlDefinition;

    // display the location object on a RotatingGlobe object
    this.display = geoLocationDisplay;

    // move the marker depiciting the location to the specified position
    this.moveMarker = geoLocationMoveMarker;

    // hide the marker depiciting the location
    this.hideMarker = geoLocationHideMarker;

    // show the location popup near the geo location
    this.showPopup = geoLocationShowPopup;

    // hide the location popup near the geo location
    this.hidePopup = geoLocationHidePopup;

    // Tell if the longitude coordinate of the GeoLocation object is visible
    // from a reference viewpoint.
    this.longitudeVisible = geoLocationLongitudeVisible;
}

/**
 *  Create the CSS definition for this location
 *
 *  @return the CSS definition for this location, as a string
 */
function geoLocationStyleDefinition()
{
    return '#' + this.id + '{'
         + ' position: absolute; '
         + ' top:      0px; '
         + ' left:     0px; '
         + '}\n';
}

/**
 *  Create the HTML element source for this location
 *
 *  @return the HTML element source for this location, as a string.
 */
function geoLocationHtmlDefinition()
{
    return '<a id="' + this.id + '" href="' + this.url + '">'
         + '<img name="' + this.id + '" alt="' + this.name + '" '
            + 'src="' + this.markerImage + '" '
            + 'width="' + this.markerWidth + '" '
            + 'height="' + this.markerHeight + '" border="0"/>'
         + '</a>\n';
}

/**
 *  Move the marker depicting the location to the specified coordinates.
 */
function geoLocationMoveMarker()
{
    var locationObject = new getObj(this.id);
    locationObject.style.top        = this.y + "px";
    locationObject.style.left       = this.x + "px";
    locationObject.style.visibility = "visible";
}

/**
 *  Hide the Marker depicting the location.
 */
function geoLocationHideMarker()
{
    var locationObject = new getObj(this.id);
    locationObject.style.visibility = "hidden";
}

/**
 *  Show the popup text near the location.
 */
function geoLocationShowPopup()
{
    replaceContent("locationPopup", this.name);

    var popup = new getObj("locationPopup");
    // display a bit to the right and above
    popup.style.left       = (this.x + 10) + "px";
    popup.style.top        = (this.y - 15) + "px";
    popup.style.visibility = "visible";
}

/**
 *  Hide the popup near the location.
 */
function geoLocationHidePopup()
{
    var popup = new getObj("locationPopup");
    popup.style.visibility = "hidden";
}


/**
 *  Display the location on the map.
 *
 *  @param globe a RotatingGlobe object, on which to display the location
 */
function geoLocationDisplay(globe)
{
    longStepSize  = 360.0 / globe.maxPosition;
    viewLongitude = globe.position * longStepSize;

    if (!this.longitudeVisible(viewLongitude)) {
        this.hideMarker();
        return;
    }

    lambda  = toRadii(this.longitude);
    phi     = toRadii(this.latitude);
    lambda1 = toRadii(viewLongitude);
    phi1    = toRadii(0);

    x = (orthographicX(phi, lambda, phi1, lambda1) * (globe.realGlobeWidth/2))
      + (globe.globeImage.width / 2);
    y = globe.globeImage.height
      - ((orthographicY(phi, lambda, phi1, lambda1) * (globe.realGlobeHeight/2))
         + (globe.globeImage.height / 2) );

    this.x = globe.globeImageX + x;
    this.y = globe.globeImageY + y;

    this.moveMarker();
}

/**
 *  Tell if the longitude coordinate of the GeoLocation object is visible
 *  from a reference viewpoint.
 *  It's not visible if it would be "on the other side of the planet"
 *
 *  @param refLongitude the reference view point, to check from.
 *  @return true if longitude is visible, false otherwise
 */
function geoLocationLongitudeVisible(refLongitude)
{
    var westEdge = refLongitude - 90;
    var eastEdge = refLongitude + 90;

    if (westEdge >= 0 && eastEdge < 360) {
        return westEdge <= this.longitude && this.longitude <= eastEdge;
    } else if (eastEdge >= 360) {
        eastEdge -= 360;
        return westEdge <= this.longitude || this.longitude <= eastEdge;
    } else {
        westEdge += 360;
        return westEdge <= this.longitude || this.longitude <= eastEdge;
    }
}


