var LS = {};
var map;
var vector_layer;
var chart_cutoff_percentage = 2.5;
var wms_url = 'http://mapserv.landsummary.com/cgi-bin/mapserv?map=/projects/landsummary/LandSummary/Yali/nlcd.map&transparent=true&';
//var rcheck; var rcheck_url = 'http://localhost/cgi-bin/mapserv?map=/var/www/tinker/nlcd.map&transparent=true&';
//wms_url = 'http://75.51.135.219/cgi-bin/mapserv?map=/var/www/tinker/nlcd.map&transparent=true&';
var tc_url = 'http://tilecache.landsummary.com/tilecache.py?'
//tc_url = 'http://mapserv.landsummary.com/cgi-bin/mapserv?map=/projects/landsummary/LandSummary/Yali/nlcd.map&transparent=true&';

var  SQ_M_PER_ACRE =  4047 ;
var  SQ_M_PER_MILE =  2589988 / 1434;
var  SQ_M_TO_SQ_KM = 1.0 / (1000 * 1000);

var agland, total_area, xy;

// avoid pink tiles
OpenLayers.IMAGE_RELOAD_ATTEMPTS = 3;
OpenLayers.Util.onImageLoadErrorColor = "transparent";

function poly_added(feature){
    var f = feature.feature;
    if (f.is_buffer){ return true; }
    // hack-crap-ulous. but preFeatureInsert messes things up.
    if (vector_layer.features.length > 1){
        vector_layer.destroyFeatures([vector_layer.features[0]]);
        }
    // check area.
    if (f.geometry.getArea() > 5001000100) {
        vector_layer.destroyFeatures([vector_layer.features[0]]);
        alert('please draw a smaller polygon')
        }
    request_params = {'services': 'population,nlcd', 'geom': f.geometry.toString()}
    request_params = set_airport_arid(request_params)
    jQuery.getJSON('/summary/', request_params, LS.handle_json);

    return true;
}

LS.handle_json = function(json){
    // k wouild be populatin, nlcd, etc.
    // dispatches to LS.handlers.population(json.population);
    for(var k in json){
        LS.handlers[k](json[k]);
    }
};
LS.handlers = {
    population: function(json){
        var pop = json['pop100'];
        if (jQuery('#pop_dens')){
            var area = json['area']
            var density = (pop / (area * SQ_M_TO_SQ_KM) ).toFixed(1);
            var dyk = 'There are ' + pop + ' persons in your block-group based calculation, for a density of:<b> ' + density + ' persons/km2</b>'
            jQuery('#pop_dens').html(dyk)
        }
        if (jQuery('#ag_summary')){
            var pop = json['pop100'];
            var ppa = (pop / (agland / SQ_M_PER_ACRE)).toFixed(1)
            var dyk = 'In the ' + (total_area * SQ_M_TO_SQ_KM).toFixed(1) + ' square KM you selected, there are' +
             ' approximately ' + pop + ' people, and '  + (agland * SQ_M_TO_SQ_KM).toFixed(2) +
             ' sq. KM of agricultural land (' +ppa + ' people per acre of agricultural land)';
            jQuery('#ag_summary').html(dyk)
        }
    },
    albedo: function(json){
       jQuery('#albedo').html('albedo: ' + json.toFixed(4))
    },

    bowen: function(json){
       try {var rslt = json.toFixed(4);}
       catch (e) {var rslt = json}
       jQuery('#bowen').html('bowen: ' + rslt );
    },

    nlcd: function(json){
        //document.getElementById('debug').innerHTML = json;
        var chl = [];
        var t = [];
        var chco = [];
        var total_pct = 0;
        agland = 0;
        var urban = 0;
        total_area = 0;
        var legend = {};
        jQuery.each(json, function(class_id, landclass) {
            total_area += landclass.total;
            if (class_id == 81 || class_id == 82) { agland += landclass.total;}
            if (class_id == 23 || class_id == 24) { urban  += landclass.pct_area;}
            if (landclass.pct_area > chart_cutoff_percentage) {
                t.push(landclass.pct_area.toFixed(4) );
            chl.push('C' + class_id + ' (' + (landclass.pct_area.toFixed(1)) + '%)');
                legend[class_id] = getDescription(class_id) + ' (' + (landclass.total * SQ_M_TO_SQ_KM).toFixed(1) + ' KM)';
                chco.push(getColor(class_id));
                total_pct += landclass.pct_area ;
                }
            });
        if (urban > 50){
            vector_layer.features[0].style = {'fillColor': '#ff0000', 'fillOpacity': '0.4', 'strokeColor': '#000000', 'strokeWidth': 2}
        }
        else {
            vector_layer.features[0].style = {'fillColor': '#0000ff', 'fillOpacity': '0.4', 'strokeColor': '#000000', 'strokeWidth': 2}
        }
        vector_layer.drawFeature(vector_layer.features[0]);
        last_t = (100 - total_pct).toFixed(4);
        t.push(last_t);
        chl.push('Other');
        chco.push('5F5F5F');
        var chart_url = 'http://chart.apis.google.com/chart?chs=350x100&cht=p3&chd=t:' + t.join(',') + '&chl=' + chl.join('|') + '&chco=' + chco.join('|');
        var i = new Image();
        i.src = chart_url;
        jQuery('#chart').html(i);

        function displayLegend(legend){
            jQuery('#legend').empty();
            jQuery.each(legend, function (class_id, desc){
                legend_row = '<div class=legend_detail  style="padding-left:4px; border-left: 16px solid #' + getColor(class_id) + ';">'
                legend_row += 'C' + class_id + ': ' + desc + '</div>';
                jQuery('#legend').append(legend_row);
                });
            }
        displayLegend(legend);
    }

}

function show_detailed_instructions(){
        var d=jQuery('#detailed_instructions');
        d.css('top', jQuery('#map').position().top + 15);
        d.css('left', jQuery('#map').position().left + 55);
        d.css('width', jQuery('#map').width() - 110);
        d.css('height', jQuery('#map').height() - 50);
        d.show();

       }

function toggle_instructions(){
    var l = jQuery('#instructions_link');
    if(l.html() == 'show'){
        l.html('hide');
        jQuery('#instructions').show()
    }else{
        l.html('show');
        jQuery('#instructions').hide()
    }
    return false;
}

jQuery(function(){
    jQuery('.spinner').ajaxStart(function(){
            jQuery(this).show();
    });
    jQuery('.spinner').ajaxStop(function(){
            jQuery(this).hide();
    });

    jQuery('#additional_dl').click(function(){
            var href = LS.download_tiff();
            if (href){
                this.href = href;
            }
            else {
                return false;
            }
    });
    jQuery('#buffer_size').change(function(){
        if(parseInt(this.value) > 80){
            alert('choose a value < 80');
            this.value = 80;
        }
    });

    jQuery('#instructions_link').click(toggle_instructions);

    jQuery('.albo').change(onMonthSeasonChange);

});

LS.download_tiff = function(link_only){
    var area = map.getExtent().toGeometry().getArea();
    if(area > 7186421727){
        // about 13 megabytes.
        alert('Please choose a smaller area');
        return false;
    }
    var bbox = map.getExtent().toBBOX();
    var l;
    var i = map.layers.length - 1;
    var layer;
    for(;l=map.layers[i]; i--){
        if(!l.getVisibility()){ continue; }
        if(l.CLASS_NAME != "OpenLayers.Layer.WMS"){ continue; }
        if(l.name.indexOf('Weather') != -1){ continue; }
        layer = l;
        break;
    }
    if(!layer){
        alert('Turn on the layer you wish to download');
        return false;
    }
    var url = '/download/?bbox=' + bbox + '&layer=' + layer.name
    if(link_only){ return url; }
    window.location.pathname = url;
};

LS.link_to_slicer = function(and_go){
    var g = vector_layer.features[0].geometry
    var ctr = g.bounds.getCenterPixel()
    var url = escape('/download/?ctr=' + ctr.x + "," + ctr.y + '&layer=NLCD&format=png')
    url = '/slicer/?image_path=' + url;
    if(and_go){
        window.open(url);
    }
    else {
        return url;
   }
};

// find if it's the 1992 or 2001 data they're looking at.
LS.get_active_year = function(){
    if(LS.nlcd_1992.visibility){ return 1992 }
    return 2001;
}

function getDescription(class_id){
    return land_classes[class_id][0];
}


function getColor(class_id){
    var rgb = color_map[class_id];
    hex = ''
    jQuery.each(rgb, function(q, N) {
        N=parseInt(N);
        if (N==0 || isNaN(N)) hex += '00';
        else {
            N=Math.max(0,N); N=Math.min(N,255); N=Math.round(N);
            hex += "0123456789ABCDEF".charAt((N-N%16)/16)
                  + "0123456789ABCDEF".charAt(N%16);
            }
        });
    return hex;
    }


function parseNewCentroid(xy){
    var r = parseInt(1000.0 * jQuery('#buffer_size').val());
    if(jQuery('#buffer_shape').val() == 'circle'){
        LS.poly = OpenLayers.Geometry.Polygon.createRegularPolygon(new OpenLayers.Geometry.Point(xy.lon, xy.lat),r,40,0);
    }
    else if (jQuery('#buffer_shape').val() == 'square'){
        r /= 2.
        var left   = xy.lon - r;
        var bottom = xy.lat - r;
        LS.poly = new OpenLayers.Bounds(left, bottom, left + 2.0 * r, bottom + 2.0 * r).toGeometry();
    }
    else {
        alert('not a valid buffer shape');
        return false;
    }
    LS.current_radius = r;
    vector_layer.destroyFeatures();
    var feature = new OpenLayers.Feature.Vector(LS.poly);
    feature.is_buffer = true;
    vector_layer.addFeatures([feature]);

    var request_params = {};

    var epsg = map.projection.getCode().substr(5)
    if (xy.lon){
        request_params = {'x': xy.lon, 'y': xy.lat, 'shape': jQuery('#buffer_shape').val(), 'radius': r, 'epsg': epsg}
    } else {
        request_params = {'geom': geom };
    }
    request_params.services = 'population,nlcd';
    request_params.nlcd_year = LS.get_active_year();
    request_params = set_airport_arid(request_params);
    var do_precip = false;
    try {
        request_params = checkAlboInputs(request_params);
        do_precip = true;
    }
    catch(E){
        do_precip = false;
        // no albo, bowen info
    }

    jQuery.getJSON('/summary/', request_params, LS.handle_json);
    jQuery('#download_csv').html('<a href="/summary/?' + jQuery.param(request_params) + '&format=csv">Download CSV</a>');

    // add a download link for the csv of the station, months used for the bowen and albedo calcs.
    if (do_precip){
        request_params['services'] = 'weather.precip';
        request_params['csv'] = ',';
        var link = '<a target="_blank" href="/summary/?' + jQuery.param(request_params) + '">Stations for Bowen calcs</a> ';
        request_params['csv'] = 'download';
        var link_dl = ' <a target="_blank" href="/summary/?' + jQuery.param(request_params) + '">(download)</a>';
        jQuery('#precip_csv').html(link + link_dl);
    }
    jQuery('#slicer_link').html('<a target="_blank" href="' + LS.link_to_slicer() + '">Surface Roughness Slice Tool</a>');

}


function onLatLonChange(){
    var clat = jQuery('#centroid_lat')[0].value;
    var clon = jQuery('#centroid_lon')[0].value;
    if(! (clat && clon)) { return ; }
    var pt = new OpenLayers.LonLat(clon, clat);
    LS.current_pt = pt.transform(map.displayProjection,map.projection);
    LS.current_pt.epsg = map.projection.getCode().substr(5)
    map.setCenter(LS.current_pt);
    parseNewCentroid(pt);
}

function set_airport_arid(request_params){
    if(!request_params){ request_params = {};}
    if (!LS.arid_cbx) LS.arid_cbx = jQuery('#arid');
    //if (!LS.airport_cbx) LS.airport_cbx = jQuery('#airport');
    request_params['arid'] = LS.arid_cbx.filter(':checked').length ? 't' : 'f';
    //request_params['airport'] = LS.airport_cbx.filter(':checked').length ? 't' : 'f';
    return request_params;
}

function checkAlboInputs(request_params){
    if(!request_params){ request_params = {};}
    if(!request_params.services){
        request_params.services = "";
    }
    else {
        request_params.services += ",";
    }
    var complete = true;
    var divs = ['start_month','stop_month','season', 'start_year'];
    if (!jQuery('#' + divs[0])){ throw "Incomplete"; }
    jQuery.each(divs, function(i,d){
            var v = jQuery('#' + d)[0].value;
            if(v == '0') {complete = false;}
            request_params[d] = v;
        });
    if (parseInt(request_params.start_year)) {
        if (parseInt(request_params.start_month) > parseInt(request_params.stop_month)) {var year_diff = 1;}
        else {var year_diff = 0}
        jQuery('#end_year')[0].innerHTML = 'through ' + (parseInt(request_params.start_year) + year_diff);
        }
    if (!complete) {
        request_params.services = request_params.services.replace(/,$/,"");
        throw "Incomplete";
    }
    request_params['services'] += 'albedo,bowen';
    return request_params;
}

function onMonthSeasonChange(){
    //if (!LS.current_pt) {alert('you need to select a location before selecting dates');return;}
    var request_params = {'x': LS.current_pt.lon, 'y': LS.current_pt.lat, 'shape': jQuery('#buffer_shape').val(), 'radius': LS.current_radius, 'epsg': LS.current_pt.epsg }
    do_precip = false;
    request_params = set_airport_arid(request_params);
    request_params.nlcd_year = LS.get_active_year();
    try {
        request_params = checkAlboInputs(request_params);
        do_precip = true;
    }
    catch(E) {
        return false;
    }
    jQuery.getJSON('/summary/', request_params, LS.handle_json);
    if (do_precip){
        request_params['services'] = 'weather.precip';
        request_params['csv'] = ',';
        var link = '<a target="_blank" href="/summary/?' + jQuery.param(request_params) + '">Stations for Bowen calcs</a> ';
        request_params['csv'] = 'download';
        var link_dl = ' <a target="_blank" href="/summary/?' + jQuery.param(request_params) + '">(download)</a>';
        jQuery('#precip_csv').html(link + link_dl);
    }
}

function updateLatLon(xy){
    var pt = new OpenLayers.LonLat(xy.lon, xy.lat);
    pt.transform(map.projection, map.displayProjection);
    pt.epsg = map.displayProjection.getCode().substr(5)
    LS.current_pt = pt;
    jQuery('#centroid_lat').val( pt.lat.toFixed(5) );
    jQuery('#centroid_lon').val( pt.lon.toFixed(5) );
}

// when the user has clicked a station and wants to see the time-series info.
function stnquery(xy){
    var epsg = map.projection.getCode().substr(5)
    jQuery('#chart').html('<img src="' +
              '/services/weather/precip/plot/?' +
                jQuery.param({'x': xy.lon, 'y': xy.lat, 'epsg': epsg}) +
                '" />');
}

function mapclick(e){
    xy = map.getLonLatFromViewPortPx(e.xy);
    clearOldResults();
    if( jQuery("input[name=nav_toggle]:checked").val()  == 'stnquery'){ return stnquery(xy); }


    updateLatLon(xy);
    parseNewCentroid(xy);
    return false;
}

function clearOldResults(){
    var divs = ['#chart','#legend','#debug','#download_csv','#ag_summary','#pop_dens'];
    jQuery.each(divs, function(i, div) {
        if (jQuery(div)) {
            jQuery(div).empty();
            }
        });
}

function init(){

    var options = {
        //controls: [new OpenLayers.Control.MouseDefaults()],
        projection: new OpenLayers.Projection("EPSG:900913"),
        displayProjection: new OpenLayers.Projection("EPSG:4326"),
        units: "m",
        //numZoomLevels: 18,
        maxResolution: 156543.0339,
        maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34,
                                         20037508.34, 20037508.34)
    };
    map = new OpenLayers.Map('map', options);


    //add some controls
    zb = new OpenLayers.Control.ZoomBox(
        {title:"Zoom box: Selecting it you can zoom on an area by clicking and dragging."});
    var panel = new OpenLayers.Control.Panel({defaultControl: zb});
     panel.addControls([
        new OpenLayers.Control.MouseDefaults(
            {title:'Pan Mode'}),
        zb,
        new OpenLayers.Control.DrawFeature(vector_layer, OpenLayers.Handler.Path,
            {title:'Draw a feature'}),
        new OpenLayers.Control.ZoomToMaxExtent({title:"Zoom to the max extent"})
        ]);
    //map.addControl(panel);
    map.addControl(new OpenLayers.Control.ScaleLine())

    map.events.register('click', map, mapclick);

    // create Google Mercator layers
    var gmap = new OpenLayers.Layer.Google(
        "Google Streets",
         {type: G_PHYSICAL_MAP,
         'sphericalMercator': true}
    );

    // create OSM layer
    var mapnik = new OpenLayers.Layer.TMS(
        "OpenStreetMap (Mapnik)",
        "http://tile.openstreetmap.org/",
        {
            type: 'png', getURL: osm_getTileURL,
            displayOutsideMaxExtent: true,
            attribution: '<a href="http://www.openstreetmap.org/">OpenStreetMap</a>'
        }
    );


    LS.nlcd_2001 = new OpenLayers.Layer.WMS("NLCD 2001", tc_url,
        {transparent: 'TRUE',
            //layers: 'nlcd92'
            layers: 'landsummary'
            //layers: 'nlcd'
        },
        {'reproject': true, opacity:.8, visibility:true}
    );
    LS.nlcd_1992 = new OpenLayers.Layer.WMS("NLCD 1992", tc_url,
        {transparent: 'TRUE',
            layers: 'nlcd92'
        },
        {'reproject': true, opacity:.8, visibility:false}
    );


    function nlcd_change(e){
        var other_layer = this == LS.nlcd_2001 ? LS.nlcd_1992 : LS.nlcd_2001;
        /* doesnt matter if both layers are off */
        if(! this.visibility){ return false; }
        /* but dont want them both on. so here, this layer must be visible.
         * so we either assure the other one is off ... */
        if(!other_layer.visibility){ return false; }
        /* or turn it off */
        other_layer.setVisibility(false)
        onMonthSeasonChange(); // recalc bowen/albdeo.
    }
    LS.nlcd_2001.events.register('visibilitychanged', LS.nlcd_2001, nlcd_change);
    LS.nlcd_1992.events.register('visibilitychanged', LS.nlcd_1992, nlcd_change);



    var weather_wms = new OpenLayers.Layer.WMS('Weather Stations',tc_url,{'layers':'weatherstations','transparent':'true'},{});
    //rcheck = new OpenLayers.Layer.WMS("rcheck", rcheck_url, {transparent: 'TRUE', layers: 'rcheck' }, {'reproject': true, opacity:.7});

    // create a vector layer for drawing
    vector_layer = new OpenLayers.Layer.Vector("Vectors");
    vector_layer.displayInLayerSwitcher = false;
    //vector_layer.events.register('beforefeaturesadded', vector_layer, vector_layer.destroyFeatures);
    vector_layer.events.register('featureadded', vector_layer, poly_added);

    var hoptions = {handlerOptions: {freehand: true}};
    var polygon_control = new OpenLayers.Control.DrawFeature(vector_layer, OpenLayers.Handler.Polygon, hoptions)
    map.addControl(polygon_control);

    jQuery('input[name=nav_toggle]').click(function(){
            // TODO: make sure this works in IE.
            if(this.value == 'draw' && ! polygon_control.active){
                vector_layer.destroyFeatures();
                polygon_control.activate();
            }
            else{
                polygon_control.deactivate();
            }

    });

    map.addLayers([mapnik, gmap, LS.nlcd_1992, LS.nlcd_2001]);


    if(true || jQuery('#environ')[0]) {map.addLayer(weather_wms)}


    map.addLayer(vector_layer);

    map.addControl(new OpenLayers.Control.LayerSwitcher());
    map.addControl(new OpenLayers.Control.Permalink());
    map.addControl(new OpenLayers.Control.MousePosition());
    map.setCenter(new OpenLayers.LonLat(-122.2,38.0).transform(map.displayProjection, map.projection),10);
    //vector_layer.preFeatureInsert = function(){ vector_layer.destroyFeatures(); }


}

function osm_getTileURL(bounds) {
    var res = this.map.getResolution();
    var x = Math.round((bounds.left - this.maxExtent.left) / (res * this.tileSize.w));
    var y = Math.round((this.maxExtent.top - bounds.top) / (res * this.tileSize.h));
    var z = this.map.getZoom();
    var limit = Math.pow(2, z);

    if (y < 0 || y >= limit) {
        return OpenLayers.Util.getImagesLocation() + "404.png";
    } else {
        x = ((x % limit) + limit) % limit;
        return this.url + z + "/" + x + "/" + y + "." + this.type;
    }
}
