﻿/*
 * @author: Charlie Szymanski
 * @created: July 31, 2007 
 * @name: property_script.js
 * @purpose: Display properties ona map similar to the "Homes" tab on Ibiseye. Property can be multilayerd and 
             include tax data. Will hopefully incorporate paging through the data when a single location has hundreds
             of individual properties.
 */
 
 
 //Global for managing homes
var homesManager;
//unfortunate global for tracking currently open parcel
var currentParcel;
var currentMarker = null;
//switch for allowing damage reports
var allowDamageReport = false;
//how many properties to show per page in bubble
var propertiesPerPage = 15;


var HomesManager = Class.create();


var homesMarkerManager = null;

HomesManager.prototype = {
    /**
     *initialies new HomesManager object and listens to the map for zooming.
     *
     **/
    initialize: function(){
        this.homeArray = new Array();
        this.oosHomeArray = new Array();
        this.firstTime = true;
        this.areHomesShown = false;
        this.infoWindowOpened = false;
        this.openProperty = null;
        //have to make sure we're on the appropriate zoom level before loading or showing homes, so listen for the zoomend
        GEvent.addListener(map, "zoomend", function(oldLevel, newLevel){
            if(newLevel >= 17){
                this.showHomes();
            }else{
                this.hideHomes();
                this.firstTime = false;
                //remove the search marker if it exists
                if(homeSearchMarker != null) map.removeOverlay(homeSearchMarker);
            }
        }.bind(this));
        
    },
    /**
     *gets map bounds and loads Homes based on them
     *
     **/
    getHomes: function(){
         //trackStats("homesDash", "Viewed Homes" );
        if(this.infoWindowOpened) return;
        showLoading();
        //first, we get the bounds of the map
        var bounds = map.getBounds();
        var sw = bounds.getSouthWest();
        var ne = bounds.getNorthEast();
       
        var swlat = sw.lat();
        var swlng = sw.lng();
        var nelat = ne.lat();
        var nelng = ne.lng();
        //then call the alerts based on those bounds
        //property.srvGetParcels(""+swlat, ""+swlng, ""+nelat, ""+nelng, this.getHomes_result.bind(this) );
        property.srvGetParcels(""+swlat, ""+swlng, ""+nelat, ""+nelng, this.getHomes_result.bind(this));
     
    },
    /**
     *Loads the AJAX data from the srvGetParcels function
     *@params (r): .NET DataSet
     **/
    getHomes_result: function(r){
         var ds = r.value;
         if(ds == null) return;
         var rows = ds.Tables[0].Rows.length;
         var rows2 = 0;//ds.Tables[1].Rows.length;
         //console.log(rows2);
         //clear out the current marker array
         this.clearOutHomes();
         //var newHomeMarkers = new Array();
         //if no alerts, let's not continue.
	     if( (rows == 0) && (rows2 == 0) ){
	        hideLoading();
	     
	        return;
	     }
	     
	     for( var i=0; i < rows; i++ ){
	        var row = ds.Tables[0].Rows[i];
	        var data = this.buildData(row, i);
            var newHome = new Home(data);
            this.homeArray.push(newHome);
         }
         //for out of state homes, not required here
         /*if( (rows2 != 0) ){
            for( var j=0; j < rows2; j++ ){
	            var row = ds.Tables[1].Rows[j];
	            var data = this.buildData(row, j);
	           // console.log(data);
                var newHome = new Home(data);
                this.oosHomeArray.push(newHome);
             }
         }*/
         //add home to dashboard
           
        hideLoading();
        
    },
    
    buildData: function(row, index){
        var data = new Hash();
        data.id = row.PARCELID;
	    data.situs = row.SITUS;
	    data.buildClass = row.BIG_TYPE;
	    data.county = row.COUNTY;
	    data.buildCat = row.BIG_TYPE;
	    data.buildType = row.SMALL_TYPE;
	    data.lat = row.LAT;
	    data.lng = row.LON;
	    data.index = index;
	    data.icon = row.ICON;
	    
	    
	    return data;
    },
   
   
    /**
     *Allows the manager to listen to move ends. Also applies to zoomends.
     *
     **/
    showHomes: function(){
       this.areHomesShown = true;
       this.getHomes();
       //this may be stupid, but I think it'll stop the data from getting sucked in twice when the event is a zoom
       //instead of a pan -- otherwise the data starts getting overwritten because it returns twice
       this.tempMoveListener = GEvent.addListener(map, "moveend", function(){
            GEvent.removeListener(this.tempMoveListener);
            this.addMoveListener();
       }.bind(this));
       //this.addMoveListener();
    },
    /**
     *stops the manager from listening to map movements -- probably a good idea if no markers are going to be displayed
     *
     **/
    hideHomes: function(){
        this.removeMoveListener();
        this.areHomesShown = false;
        this.clearOutHomes();
    },
    
    //adds listener for map moving to reload the homes
    addMoveListener: function(){
        if(this.mapListener == null){
           this.mapListener = GEvent.addListener(map, "moveend", function(){
                                    this.getHomes();
                              }.bind(this));
       }
    },
    //removes the above listener so homes don't load as that map is moved
    //this allows us to turn off the listener if an info-window is opened.
    removeMoveListener: function(){
        if(this.mapListener)
            GEvent.removeListener(this.mapListener);
        this.mapListener = null;
    },
    
    showProperties: function(index){
        this.openProperty.showProperties(index);
    },
   /**
     *Kills all of the wind arrows in the wind array
     *
     **/
    clearOutHomes: function(){
        var survived = null;
        
        this.homeArray.each(function(home, index){
            var destroyed = home.destroy();
        //    if(!destroyed) survived = home;
        });
        this.homeArray = new Array();
        
        this.oosHomeArray.each(function(home, index){
            var destroyed = home.destroy();
        //    if(!destroyed) survived = home;
        });
        this.oosHomeArray = new Array();
        
    }
}

var Home = Class.create();

Home.prototype = {
    /**
     *Creates a wind arrow -- contains the data for that arrow, a GIcon, some html for the tootip, a GLatLng,
     * and a GMarker for displaying on the map
     *@params(data): a wind data object created by the WindManager.
     **/
    initialize: function(data){
        this.locationData = data;
        this.propertyArray = new Array();
        this.propertyArraySlices = new Array();
        this.propertyCount = 0;
        this.propertyPages = 1;
        //this.dataArray = new Array();
        this.icon = this.getIcon(data.icon);
        this.html = new Array();
       // var infoHtml = this.buildBubble(data);
        this.html.push(new GInfoWindowTab("Info", "<div class='homesBubbleSizer'><div id='dataTarget'></div></div>"));
        this.point = new GLatLng(data.lat, data.lng);
        this.marker = this.createMarker(this.point,this.html,this.icon,data.situs, data);
        this.isOpened = false;
        this.addToMap();
        
    },
    
    /*
        Passes ID to data function to get property data and use it
    */
    getData: function(){
        this.propertyArray.clear();
        this.propertyArraySlices.clear();
        
        showLoading();
        property.srvGetParcelData(this.locationData.id, this.getData_result.bind(this));
    },
    
    getData_result: function(r){
         var ds = r.value;
         if(ds == null) return;
         var rows = ds.Tables[0].Rows.length;
         //clear out the current marker array
         //var newHomeMarkers = new Array();
         //if no alerts, let's not continue.
	     if(rows == 0){
	        hideLoading();
	        return;
	     }
	     
	     for( var i=0; i < rows; i++ ){
	        var row = ds.Tables[0].Rows[i];
	        var data = this.buildData(row, i);
	        var html = this.buildBubble(data);
	        this.propertyArray.push(html);
	        //new Insertion.Bottom("dataTarget", html);
         }
         this.propertyCount = this.propertyArray.length;
         
         this.propertyArraySlices = this.propertyArray.eachSlice(propertiesPerPage);
         this.propertyPages = this.propertyArraySlices.length;
         
         this.showProperties(0);
         hideLoading();
    },
    
    showProperties: function(index){
        
        if(index == this.propertyPages){
            index = 0;
        }
        if(index < 0){
            index = this.propertyPages - 1;
        }
        
        var nextIndex = index + 1;
        var prevIndex = index-1;
            
        var arrows = "<div>" +
                        "<h4 style='float:left; margin:0 20px 0 0; padding:0;'><a href='javascript:;' onclick='homesManager.showProperties("+prevIndex+")' >Back</a></h4>" +
                        "<span style='margin:0 20px 0 20px; float:left;'>(page "+nextIndex+" of "+this.propertyPages+" pages)</span>" +
                        "<h4 style='float:left; margin:0; padding:0;'><a href='javascript:;' onclick='homesManager.showProperties("+nextIndex+")' >Next</a></h4>" +
                     "</div>";
                         
        
        
        //new Effect.BlindUp("dataTarget", {afterFinish: function(){
            $("dataTarget").innerHTML = "";
            if(propertiesPerPage <= this.propertyCount)
                new Insertion.Bottom("dataTarget", arrows);
            
            $("dataTarget").scrollTop = 0;
            this.propertyArraySlices[index].each(function(html){
                new Insertion.Bottom("dataTarget", html);
            });
           
            if(propertiesPerPage <= this.propertyCount)
                new Insertion.Bottom("dataTarget", arrows);
       // }.bind(this)});
    },
    
    buildData: function(row, index){
        var data = new Hash();
        data.id = row.ParcelID;
        data.owner = row.OWNERNAME;
	    data.addy = row.STREETADDRESS;
	    data.situs = row.SITUS;
	    data.addyType = row.ADD_TYPE;
	    data.t07 = row.T07;
	    data.j07 = row.J07;
	    data.a07 = row.A07;
	    data.buildClass = row.BIG_TYPE;
	    data.county = row.COUNTY;
	    data.buildCat = row.BIG_TYPE;
	    data.buildType = row.SMALL_TYPE;
	    data.nb = row.ZIP;
	    data.saleYear = row.SALEYEAR;
	    data.salePrice =row.SALEPRICE;
	    data.lat = row.LAT;
	    data.lng = row.LON;
	    data.ddl = row.DDL;
	    data.damage = row.JCHANGE;
	    data.index = index;
	    data.icon = row.ICON;
	    data.j06 = row.J06
	    data.t06 = row.T06
	    data.a06 = row.A06
	    data.jchange = row.JCHANGE;
	    data.achange = row.ACHANGE;
	    data.tchange = row.TCHANGE;
	    data.stax06 = row.SCH_TAX06;
	    data.stax07 = row.SCH_TAX07;
	    data.ctax06 = row.CTY_TAX06;
	    data.ctax07 = row.CTY_TAX07;
	    
	    
	    return data;
    },
    
    /**
     *Builds the HTML for a tooltip.
     *@params (data): the data used to generate the tooltip.
     **/
    buildBubble: function(data){
    
         var html = '<div class="bubbleElementContainer" style="background-color:#FFFFFF; margin-bottom:10px; border-bottom:1px solid #AAAAAA; float:left;"> '+
                        '<table>'+
                        '<tr>'+
                        '<td>'+
                        '<h4 style="margin-bottom:2px; font-size:12px;">'+data.owner+' (as of 12/31/2006)</h4> '+
                        '<h5 style="margin:2px 0 2px 0; font-size:10px;">'+data.situs+'</h5> '+
                        '<div class="bubbleElementSub">' +
                         '   <span class="bubbleLeft">County: </span><span class="bubbleRight">'+data.county+'</span>' +
                        '</div><div class="bubbleElementSub">' +
                         '   <span class="bubbleLeft">Building Category:</span><span class="bubbleRight">'+data.buildCat+'</span>' +
                        '</div><div class="bubbleElementSub">' +
                         '   <span class="bubbleLeft">Building Type: </span><span class="bubbleRight">'+data.buildType+'</span>' +
                       '</div><div class="bubbleElementSub" style="margin-bottom:15px;">' +
                         '   <span class="bubbleLeft">Most Recent Sale: </span><span class="bubbleRight">'+data.saleYear+' - ' + formatCurrency(data.salePrice)+' (as of 12/31/2006)</span>' +
                       '</div>'+
                       //'</div><div class="bubbleElementSub">' +
                       //  '   <span class="bubbleRight">*As of 12/31/2006</span>' +
                       //'</div>'+
                       '</td>'+
                       '</tr>'+
                       '</table>'+
                        '<a href="javascript:;" style="font-size:10px;" onclick="sendData(\''+data.j07+'\', \''+data.t07+'\')">Calculate values over time (results loaded below)</a>' +
                       '<table id="bubbleTable" style="margin-top:2px; padding-top:0px;">' +
                            '<tr>'+
                                '<td align="right" width="130"><span class="firstRow">Tax Year</span></td><td style="padding-left:10px;">2007</td><td>2006</td><td>Change</td>'+
                            '</tr><tr>'+
                                '<td align="right"><span class="firstRow">Total Value</span></td><td>'+formatCurrency(data.j07)+'</td><td>'+formatCurrency(data.j06)+'</td><td>'+data.jchange+'%</td>'+
                            '</tr><tr>'+
                               '<td align="right"><span class="firstRow">Assessed Value</span></td><td>'+formatCurrency(data.a07)+'</td><td>'+formatCurrency(data.a06)+'</td><td>'+data.achange+'%</td>'+
                            '</tr><tr>'+
                                '<td align="right"><span class="firstRow">Taxable Value</span></td><td>'+formatCurrency(data.t07)+'</td><td>'+formatCurrency(data.t06)+'</td><td>'+data.tchange+'%</td>'+
                            '</tr><tr>'+
                                '<td align="right"><span class="firstRow">School Taxes</span></td><td>'+formatCurrencySmall(data.stax07)+'</td><td>'+formatCurrencySmall(data.stax06)+'</td><td>'+Math.round(((data.stax07-data.stax06)/data.stax06)*10000)/100+'%</td>'+
                            '</tr><tr>'+
                                '<td align="right"><span class="firstRow">County Taxes</span></td><td>'+formatCurrencySmall(data.ctax07)+'</td><td>'+formatCurrencySmall(data.ctax06)+'</td><td>'+Math.round(((data.ctax07-data.ctax06)/data.ctax06)*10000)/100+'%</td>'+
                            '</tr><tr>'+
                                '<td align="right"><span class="firstRow">County-wide Total</span></td><td>'+formatCurrencySmall(data.ctax07+data.stax07)+'</td><td>'+formatCurrencySmall(data.ctax06+data.stax06)+'</td><td>'+Math.round((((data.ctax07+data.stax07)-(data.ctax06+data.stax06))/(data.ctax06+data.stax06))*10000)/100+'%</td>'+
                            '</tr>'+
                        '</table>'+
                        '<a href="javascript:;" style="font-size:10px;" onclick="sendData(\''+data.j07+'\', \''+data.t07+'\')">Calculate values over time (results loaded below)</a>';
                        
                      
                    html +='</div>';
         return html;
         
    },
    
    getIcon: function(type, damaged){
        //com,res,ind,con,gov,other
        //type = type.toLowerCase();
        var icon = new GIcon();
        icon.image = "images/icons/properties/"+type;
        icon.iconSize = new GSize(30, 30);
	    icon.iconAnchor = new GPoint(15,15);
	    icon.infoWindowAnchor = new GPoint(15, 15);
	    return icon;
    },
    
    createMarker: function(point,html,ic,toolText, data) {
       var marker = new GMarker(point,ic);
       marker.data = data;
       marker.tooltip = "<div class='tooltip'>"+ toolText + "</div>";
       
       GEvent.addListener(marker, "click", function() {
              //stop the map from listening to movements so the pan doesn't result in a lot of calls to the server
              homesManager.removeMoveListener();
              marker.openInfoWindowTabsHtml(html, {suppressMapPan: true});
              
              this.panToMarker();
                         
       }.bind(this));
       //when info window is finally rendered, add the alert narrative
       GEvent.addListener(marker, "infowindowopen", function(){
            homesManager.removeMoveListener();
            currentMarker = marker;
            this.isOpened = true;
            this.getData();
            homesManager.infoWindowOpened = true;
            //keep track of the opened property
            homesManager.openProperty = this;
       }.bind(this));
       GEvent.addListener(marker, "infowindowclose", function(){
            this.isOpened = false;
            homesManager.infoWindowOpened = false;
            currentMarker = null;
            homesManager.addMoveListener();
       }.bind(this));
       //listen for hovers for the tooltip.
       GEvent.addListener(marker,"mouseover", function() {
              showTooltip(marker, map);
       });      
	   GEvent.addListener(marker,"mouseout", function() {
		    tooltip.style.visibility="hidden"
       });	
       
       return marker;
   },
   
   panToMarker: function(){
        //pan within the click function -- for some reason this didn't like pannig otherwise
              var markerLocation = this.marker.getPoint();
              var pixels = map.fromLatLngToDivPixel(markerLocation);
              var center = map.getCenter();
              var centerPixels = map.fromLatLngToDivPixel(center);
              //centerPixels
              var y = pixels.y;
              y = y - 180;
              var x = pixels.x;
              x = x + 80;
              var newLatLng = map.fromDivPixelToLatLng(new GPoint(x, y));
              map.panTo(newLatLng);
   },
   
   addToMap: function(){
       this.isMapped = true;
       map.addOverlay(this.marker);
   },
   removeFromMap: function(){
       this.isMapped = false;
       map.removeOverlay(this.marker);
   },
    /**
     * Destroys this marker and hopefully realeses its memory
     *
     **/
   destroy: function(){
    //if(this.isOpened) return false;
    this.removeFromMap();
    this.marker = null;
    this.data = null;
    this.icon = null;
    this.point = null;
    this.html = null;
    return true;
   }
}






var homeSearchMarker;
/**
  *
  *Function that will do a search for a location.
  *
  **/
function getHomesSearch(){
       
        if(homeSearchMarker != null) map.removeOverlay(homeSearchMarker);
      
       //get value of location box
       var addy = $F("searchAddy");
       var city = $F("searchCity");
       var zip = $F("searchZip");
       
       //build location for search
       var location = addy + " " + city + ", FL " + zip;
       
        
        // ====== Perform the Geocoding ======        

        geocoder.getLocations(location, function (result)
        { 
            if (result.Status.code == G_GEO_SUCCESS) {
              // centre the map on the first result
              
              var p = result.Placemark[0].Point.coordinates;
              var addy = result.Placemark[0].address;
              //set center over location
              //zoom to the point that was looked up
              map.setCenter(new GLatLng(p[1],p[0]),17);
              //create marker to place on the map
              //if it's not in florida, add a super-marker
              var icon = new GIcon;
                icon.image = "http://ibis.htcreative.com/onelegged/images/icons/wind/r5_180.png";
                icon.iconSize = new GSize(31, 32);
	            icon.iconAnchor = new GPoint(15,16);
	            icon.infoWindowAnchor = new GPoint(15, 16);
                homeSearchMarker = new GMarker(new GLatLng(p[1],p[0]), icon);
              
              //add marker to map
              map.addOverlay(homeSearchMarker);
              //and close window
              //Windows.close("uniqueDashhomesDash");
              //and refresh the icons
              //homesManager.showHomes();
            }else {
               var reason="Code "+result.Status.code;
                 if (geocodingReasons[result.Status.code]) {
                    reason = geocodingReasons[result.Status.code]
                } 
                alert('Could not find "'+location+ '" ' + reason);
            }
          }
        );
}

 function formatCurrency(num) {
    num = num.toString().replace(/\$|\,/g,'');
    if(isNaN(num)){num = "0";}
    num = Math.round( (num/1000))*1000;
    sign = (num == (num = Math.abs(num)));
    num = Math.floor((num*100+0.50000000001));
    cents = num%100;
    num = Math.floor(num/100).toString();
    if(cents<10){cents = "0" + cents;}
        for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++){
            num = num.substring(0,num.length-(4*i+3))+','+
            num.substring(num.length-(4*i+3));
       }
    return (((sign)?'':'-') + '$' + num);
}

 function formatCurrencySmall(num) {
    num = num.toString().replace(/\$|\,/g,'');
    if(isNaN(num)){num = "0";}
    num = Math.round( (num/10))*10;
    sign = (num == (num = Math.abs(num)));
    num = Math.floor((num*100+0.50000000001));
    cents = num%100;
    num = Math.floor(num/100).toString();
    if(cents<10){cents = "0" + cents;}
        for (var i = 0; i < Math.floor((num.length-(1+i))/3); i++){
            num = num.substring(0,num.length-(4*i+3))+','+
            num.substring(num.length-(4*i+3));
       }
    return (((sign)?'':'-') + '$' + num);
}


/*
      var data = new Hash();
        data.id = row.ParcelID;
        data.owner = row.OWNERNAME;
	    data.addy = row.STREETADDRESS;
	    data.situs = row.SITUS;
	    data.addyType = row.ADD_TYPE;
	    data.t07 = row.T07;
	    data.j07 = row.J07;
	    data.a07 = row.A07;
	    data.buildClass = row.BIG_TYPE;
	    data.county = row.COUNTY;
	    data.buildCat = row.BIG_TYPE;
	    data.buildType = row.SMALL_TYPE;
	    data.nb = row.ZIP;
	    data.saleYear = row.SALEYEAR;
	    data.salePrice =row.SALEPRICE;
	    data.lat = row.LAT;
	    data.lng = row.LON;
	    data.ddl = row.DDL;
	    data.damage = row.JCHANGE;
	    data.index = index;
	    data.icon = row.ICON;
	    data.j06 = row.J06
	    data.t06 = row.T06
	    data.a06 = row.A06
	    data.jchange = row.JCHANGE;
	    data.achange = row.ACHANGE;
	    data.tchange = row.TCHANGE;*/