
/**
 * Class to wrap around a POI object. A POI object is a dynamic object created
 * with the following format: 
 * {longitude:144.964346,latitude:-37.810551,poiid:0,index:0,header:"street1",description:"swanston st",summary:"summary"};
 *
 * This class wraps around self object and provides functionality to render the 
 * POI onto the map.
 *
 * Author: Akshay Bhurtun
 *
 * $Id: ClientPOI.js,v 1.21 2009/07/20 07:24:20 abhurtun Exp $
 */

/**
 * Constructor takes in a poi of the format mentioed above
 */

function ClientPOI(stringifiedPOI_)
{
   var cName = "[ClientPOI] ";
   var stringifiedPOI = stringifiedPOI_;
   
   var tolerance = 10;
   var customMarkerRadius = 8;
   
   var VECTOR_MARKER = 0;
   var VECTOR_TEXT_INDEX = 1;
   var VECTOR_TOOLTIP = 2;
   var VECTOR_CLICK_AREA = 3;
   var VECTOR_HOVER_AREA = 4;
   var VECTOR_COUNT = 5;
   
   var vector = com.ptvag.webcomponent.map.vector;
   var self=this;
   
   var vectorElements = new Array();
   
   self.handleTooltipClosure = handleTooltipClosure;
   self.showToolTip = showToolTip;
   self.$=$;
   self.setVariable=setVariable;
   self.getMarkerToolTip=getMarkerToolTip;
   
   /**
    * Function to retrieve a particular attribute from the stringified object
    */
   function $(variable)
   {
      if(stringifiedPOI == null || variable == null)
         return null;
      var temp = null;
      eval("temp=stringifiedPOI." + variable);
      return temp;
   };

   /**
    * Function to set a variable within the stringified object
    *
    * @param variable - variable to set
    * @param value - value to be set to 
    */   
   function setVariable(variable, value)
   {
      if(stringifiedPOI == null || variable == null)
         return null;
      
      if($(variable) != null)
         eval("stringifiedPOI." + variable + "=" + value);
   };
   
   
   /**
    * Function to render a poi onto a layer
    * @param layer - the layer Object on which to draw this POI
    * @param displayToolTip - whether to show the tooltip or not
    */
   self.render=function render(layer, displayToolTip)
   {
      var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
      
      stringifiedPOI.x = coordAsSmartUnit.x;
      stringifiedPOI.y = coordAsSmartUnit.y;
      
      var marker = null;

      if($("imageMarker") != null && $("imageMarker").length > 0)
         marker = getImageMarker($("imageMarker"));
      else
         marker = getMarker();
      
      if(marker != null && marker.getId() == null)
      {
         var deltaX = 0;
         var deltaY = 0;
         if($("markerVAlign") != null)
            deltaY = parseInt($("markerVAlign"));
            
         if($("markerHAlign") != null)
            deltaX = parseInt($("markerHAlign"));
   
         marker.setFlexX(deltaX);
         marker.setFlexY(deltaY);
         layer.addElement(marker);
      }
      
      var markerText = getMarkerText();
      if(markerText != null && markerText.getId() == null)         
         layer.addElement(markerText);

      var clickArea = getClickArea(layer, displayToolTip);         
      if(clickArea != null && clickArea.getId() == null)
         layer.addElement(clickArea);
      
      var hoverArea = getHoverArea(layer);         
      if(hoverArea != null && hoverArea.getId() == null)
         layer.addElement(hoverArea);
   };
   
   /**
    * Function to execute user defined functions when a tooltip is closed.
    * It works like a listener 
    */
   function handleTooltipClosure(layer)
   {
      var tooltip = getMarkerToolTip();
   
      layer.removeElement(tooltip.getId());
      tooltip.setId(null);
      
      executeHandler("closeTTHandler");
   }
   
   /**
    * Function to display a tooltip when the user clicks on a POI.
    * This function has the capability of executing a user defined function
    * if such function is registered to the POI.<b> 
    * the attribute to be used to register a click handler is "clickHandler"
    *
    * @param layer - the layer object on which to display the tooltip (default vector)
    * @param closeToolTip - whether to open or close the tooltip. (Default true)
    */
   
   function showToolTip(layer, closeToolTip)
   {
      if($("hideTT") == true)
         return;
      
      executeHandler("preTTLoadHandler");
         
      if(closeToolTip == null)
         closeToolTip = true;
      var tooltip = getMarkerToolTip();
      
      if(tooltip.getId() != null)
      {
         if(closeToolTip == true)
            handleTooltipClosure(layer);
         return;
      }
      
      tooltip.setInfoBoxElementFactory(new com.ptvag.webcomponent.map.vector.InfoBoxElementFactoryRound());
      
      tooltip.setCloseWidgetHandler(function(evt)
      {
         self.handleTooltipClosure(layer);
      });
      layer.addElement(tooltip);
      executeHandler("postTTLoadHandler");
   };
   
   
   
   /**
    * Remove all of the related vectors from the map for this particular POI
    *
    * @param layer - layer from which to remove the POI from
    */
   self.clearVectorElements=function clearVectorElements(layer, dumpVector)
   {
      var fnName = cName + "clearVectorElements()";
      if(layer == null)
      {
         log.warn(fnName, "layer missing");
         return;
      }
   
      log.debug(fnName, "Clearing vector elements for POI [" + this.$("poiid") + "]");
      for(var i=0; i<VECTOR_COUNT; i++)
      {
         var currentVector = vectorElements[i];
         if(currentVector != null)
         {
            layer.removeElement(currentVector.getId());
            currentVector.setId(null);
         }
         if(dumpVector)
            vectorElements[i] = null;
      }
   };
   
   self.getVectorElements=function getVectorElements()
   {
      return vectorElements; 
   };
   
   /**
    * Util function to remove a tool tip for a particular ClientPOI object
    * @param layer - layer name from where to remove the tooltip from (default vector)
    */
   self.removeToolTip=function removeToolTip(layer, exceptPOIId)
   {
      var fnName = cName + "removeToolTip() ";
      if(layer == null)
      {
         log.info(fnName, "No layer provided, defaulting to [" + conf_default_drawingLayerName + "]");
         layer = map.getLayer(conf_default_drawingLayerName);
      }
      var tooltip = vectorElements[VECTOR_TOOLTIP];
      if(tooltip != null)
      {
         layer.removeElement(tooltip.getId());
         tooltip.setId(null);
      }
   };
   
   /*===========ACCESSORS AND MUTATORS =======================================*/
   
   /**
    * Function to return the Stringified POI {x:..,y:..,..}
    */
   self.getPOI=function getPOI()
   {
      return stringifiedPOI;
   };
   
   self.setStringifiedPOI=function setPOI(stringifiedPOI_)
   {
      stringifiedPOI = stringifiedPOI_;
      
      for(var i=0; i<VECTOR_COUNT; i++)
      {
         vectorElements[i]=null;
      }
   };
   
   /**
    * Function to get the current marker for this POI. If the marker has not been
    * created yet, this function will create and return the newly created marker
    * 
    * @return ia.vector.CustomMarker
    */
   function getMarker()
   {
      var customMarker = vectorElements[VECTOR_MARKER]; 
      if(customMarker == null)
      {
         /*var coordAsSmartUnit= {x:stringifiedPOI.x,y:stringifiedPOI.y};
         
         if(coordAsSmartUnit.x == null || coordAsSmartUnit.x == 0 ||
            coordAsSmartUnit.y == null || coordAsSmartUnit.y == 0)
            ptvWrapper.getSmartCoordinate(stringifiedPOI);*/
         customMarker = new ia.vector.CustomMarker(stringifiedPOI.x, stringifiedPOI.y);
         
         var color = $("color");
         if(color == null)
            color = "black";
         customMarker.setColor(color);
         customMarker.setFillColor($("fillColor"));
         
         var radius = $("radius");
         if(radius == null || radius == 0)
            radius = customMarkerRadius;
         customMarker.setRadius(radius);
         customMarker.setFill($("fill"));
      }
      customMarker.setPriority(parseInt($("drawPriority")));
      vectorElements[VECTOR_MARKER] = customMarker;
      return customMarker;
   };
   
   /**
    * use of an image marker instead of custom marker
    */
   function getImageMarker(imageUrl)
   {
      var imageMarker = vectorElements[VECTOR_MARKER];
      if(imageMarker == null)
      {
         //var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
         imageMarker = new com.ptvag.webcomponent.map.vector.ImageMarker();
         imageMarker.setX(stringifiedPOI.x);
         imageMarker.setY(stringifiedPOI.y);
         imageMarker.setUrl(imageUrl);
      }
      imageMarker.setPriority(parseInt($("drawPriority")));
      vectorElements[VECTOR_MARKER] = imageMarker;
      return imageMarker; 
   };
   
   /**
    * Function to get the current text to be displayed on the marker
    *
    * @return com.ptvag.webcomponent.map.vector.Text
    */
   function getMarkerText()
   {
      var fnName = cName + "getMarkerText() ";
      var textVector = vectorElements[VECTOR_TEXT_INDEX];
      if(textVector == null)
      {
         //var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
         textVector = new vector.Text();
         
         textVector.setX(stringifiedPOI.x);
         textVector.setY(stringifiedPOI.y);
         
         var label = $("label");
         var index = $("index");
         if(index == null)
            index = "";
         
         if(label == null || label.length == 0)
            label = index;
         textVector.setText("" + label);
         var fontSize = $("fontSize");
         if(fontSize == null || fontSize == 0)
            fontSize = 10;
            
         var fontFamily = $("fontFamily");
         if(fontFamily == null || fontFamily.length == 0)
            fontFamily = "Verdana,Arial,sans-serif";
            
         var fontWeight = $("fontWeight");
         if(fontWeight == null || fontWeight.length == 0)
            fontWeight = "bold";
         
         textVector.setFontWeight(fontWeight);
         textVector.setFontFamily(fontFamily);
         textVector.setPixelSize(fontSize);
         textVector.setAlignment(34);
         
         //textVector.setVerticalAdjustment(verticalAdjustment);
         var color = $("fontColor");
         if(color == null)
            color = "black";
         textVector.setColor(color);
      }
      textVector.setDependsOn(vectorElements[VECTOR_MARKER].getId());
      textVector.setPriority(parseInt($("drawPriority")));
      var deltaX = 0;
      var deltaY = 0;
      if($("textVAlign") != null)
         deltaY = parseInt($("textVAlign"));
         
      if($("textHAlign") != null)
         deltaX = parseInt($("textHAlign"));
      textVector.setFlexX(deltaX);
      textVector.setFlexY(deltaY);
      
      vectorElements[VECTOR_TEXT_INDEX] = textVector;
      return textVector;
   };
   
   /**
    * Function to get the current tooltip to be displayed.
    * 
    * @return com.ptvag.webcomponent.map.vector.InfoBox 
    */
   function getMarkerToolTip()
   {
      var tooltip = vectorElements[VECTOR_TOOLTIP];
      if(tooltip == null)
      {
         //var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
         tooltip = new com.ptvag.webcomponent.map.vector.InfoBox();
         tooltip.setX(stringifiedPOI.x);
         tooltip.setY(stringifiedPOI.y);
         
         tooltip.setId(null);
         
         tooltip.setShowCloseWidget($("hideTTCloseButton")!=true);
         tooltip.setAlignment(com.ptvag.webcomponent.map.layer.VectorLayer.ALIGN_MID_VERT);
      }
      tooltip.setPriority(parseInt($("drawPriority")));
      var deltaX = 0;
      var deltaY = 0;
      if($("ttVAlign") != null)
         deltaY = parseInt($("ttVAlign"));
         
      if($("ttHAlign") != null)
         deltaX = parseInt($("ttHAlign"));
      tooltip.setFlexX(deltaX);
      tooltip.setFlexY(deltaY);
      var summary = $("summary");
         
      if(stringifiedPOI.useRoutingInfo)
         summary = $("routingInfo");
      
      if(summary == null)
         summary = "&nbsp";
      tooltip.setText(summary);
      tooltip.setPriority(parseInt($("drawPriority")));
      vectorElements[VECTOR_TOOLTIP] = tooltip;
      return tooltip;
   };
   
   
   /**
    * Function to get a click area for a particular POI. A click area is an area
    * on a map that is sensitive to mouse clicks. The current implementation
    * will open a tooltip with some brief information regarding the POI if the
    * user clicks on that clickArea
    *
    * @param displayToolTip - whether to display the tooltip or not
    * @return  com.ptvag.webcomponent.map.vector.ClickArea
    * 
    */
   function getClickArea(layer, displayToolTip)
   {
      var clickArea = vectorElements[VECTOR_CLICK_AREA];
   
      if(clickArea == null)
      {
         //var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
         clickArea = new com.ptvag.webcomponent.map.vector.ClickArea();
         clickArea.setX(stringifiedPOI.x);
         clickArea.setY(stringifiedPOI.y);
      }
      clickArea.setPriority(parseInt($("drawPriority")));
      var custom_tolerance = stringifiedPOI.radius;
      
      if(custom_tolerance == null || custom_tolerance == 0)
         custom_tolerance = tolerance;
         
      clickArea.setTolerance(custom_tolerance);
      
      var deltaX = 0;
      var deltaY = 0;
      if($("clickVAlign") != null)
         deltaY = parseInt($("clickVAlign"));
         
      if($("clickHAlign") != null)
         deltaX = parseInt($("clickHAlign"));
      
      clickArea.setFlexX(deltaX);
      clickArea.setFlexY(deltaY);
      
      clickArea.setHandler(function(evt)
      {
         executeHandler("preClickHandler");
         showToolTip(layer);
         executeHandler("clickHandler");
      });
      
      vectorElements[VECTOR_CLICK_AREA] = clickArea;
      
      if(displayToolTip)
      {
         executeHandler("preClickHandler");
         showToolTip(layer);
         executeHandler("clickHandler");
      }
      return clickArea;
   };
   
   /**
    * Function to get a hover area associated to a particular POI. A hover area
    * is an area on the map that is sensitive to mouse hovers. The current 
    * implementation uses such area purely for changing the mouse cursor.
    * on hover a mouse cursor of type "pointer" is used. on Exitting the hover 
    * area, the cursor is reset to the default pointer.
    *
    * @return com.ptvag.webcomponent.map.vector.HoverArea
    *
    */
   function getHoverArea(layer)
   {
      var fnName = cName + "getHoverArea()";
      var hoverArea = vectorElements[VECTOR_HOVER_AREA];
      
      if(hoverArea == null)
      {
         //var coordAsSmartUnit= ptvWrapper.getSmartCoordinate(stringifiedPOI);
         hoverArea = new com.ptvag.webcomponent.map.vector.HoverArea();
         hoverArea.setX(stringifiedPOI.x);
         hoverArea.setY(stringifiedPOI.y);
      }
      hoverArea.setDependsOn(vectorElements[VECTOR_MARKER].getId());
      hoverArea.setPriority(parseInt($("drawPriority")));
      var custom_tolerance = stringifiedPOI.radius;
      
      if(custom_tolerance == null || custom_tolerance == 0)
         custom_tolerance = tolerance;
         
      hoverArea.setTolerance(custom_tolerance);
      
      var deltaX = 0;
      var deltaY = 0;
      if($("hoverVAlign") != null)
         deltaY = parseInt($("hoverVAlign"));
         
      if($("hoverHAlign") != null)
         deltaX = parseInt($("hoverHAlign"));

      hoverArea.setFlexX(deltaX);
      hoverArea.setFlexY(deltaY);
      
      hoverArea.setHoverHandler(function(evt)
      {
         map.setCursor("pointer");
         if(!stringifiedPOI.disableTTOnHover)
            showToolTip(layer, false);
         executeHandler("hoverHandler", evt);
      });
      
      hoverArea.setUnhoverHandler(function(evt)
      {
         map.setCursor("default");
         executeHandler("exitHoverHandler");
      });
      
      vectorElements[VECTOR_HOVER_AREA] = hoverArea;
      return hoverArea;
   };
   
   function executeHandler(handlerName)
   {
      var fnName = cName + "executeHandler()";
      var handlerFn = $(handlerName);

      if(typeof(handlerFn) != null && typeof(handlerFn) == "function")
      {
         handlerFn(self);
      }
      
      //log.debug(fnName, "Executing handler: [" + handlerName + "] - [" + handlerFn + "]");
      else if(handlerFn != null || (""+handlerFn).length > 0)
         eval("" + handlerFn);
   }
   
   /**
    * @param poi - clientPOI object
    */
   self.copyVariables=function copyVariables(poi)
   {
      var fnName = cName + "copyVariables() ";
      
      /*//pois[i].clearVectorElements(map.getLayer("vector"));
      var attributes = ["hoverHandler", "exitHoverHandler", 
                        "closeTThandler", "preTTLoadHandler", "postTTLoadhandler",
                        "clickHandler", "preClickHandler", 
                        "categoryId", "imageMarker", "label", "hideTT", "hideTTCloseButton", 
                        "fontFamily", "fontWeight", "fontSize", "routeId"];
                        
      for(var j=0; j<attributes.length; j++)
      {
         
         if($(attributes[j]) == null || (""+$(attributes[j])).length == 0)
         {
            setVariable(attributes[j], "\"" + poi.$(attributes[j]) + "\"");
         }
      }
      // set the ints
      setVariable("textVAlign", poi.$("textVAlign"));
      setVariable("textHAlign", poi.$("textHAlign"));
      setVariable("hoverVAlign", poi.$("textVAlign"));
      setVariable("hoverHAlign", poi.$("clickHAlign"));
      setVariable("clickVAlign", poi.$("clickVAlign"));
      setVariable("clickHAlign", poi.$("clickHAlign"));
      setVariable("markerVAlign", poi.$("markerVAlign"));
      setVariable("markerHAlign", poi.$("markerHAlign"));
      setVariable("radius", poi.$("radius"));*/
      
      for(var attr in poi.getPOI())
      {
         //log.debug(fnName, "attr [" + attr + "] type [" + typeof(attr) + "]");
         if(attr != "poiid")
            eval("poi.getPOI()." + attr + " = stringifiedPOI." + attr); 
      }
      
   }
   
}