var h = 700; 
var w = 700;

var projection = d3.geo.mercator()
                       .center([-76.612223, 39.294504])
                       .scale([150000])
                       .translate([310, 290]);

var comma_format = d3.format(",");

// viridis colors
var viridis_colors = ["#440154","#440256","#450457","#450559","#46075a","#46085c","#460a5d","#460b5e","#470d60","#470e61","#471063","#471164","#471365","#481467","#481668","#481769","#48186a","#481a6c","#481b6d","#481c6e","#481d6f","#481f70","#482071","#482173","#482374","#482475","#482576","#482677","#482878","#482979","#472a7a","#472c7a","#472d7b","#472e7c","#472f7d","#46307e","#46327e","#46337f","#463480","#453581","#453781","#453882","#443983","#443a83","#443b84","#433d84","#433e85","#423f85","#424086","#424186","#414287","#414487","#404588","#404688","#3f4788","#3f4889","#3e4989","#3e4a89","#3e4c8a","#3d4d8a","#3d4e8a","#3c4f8a","#3c508b","#3b518b","#3b528b","#3a538b","#3a548c","#39558c","#39568c","#38588c","#38598c","#375a8c","#375b8d","#365c8d","#365d8d","#355e8d","#355f8d","#34608d","#34618d","#33628d","#33638d","#32648e","#32658e","#31668e","#31678e","#31688e","#30698e","#306a8e","#2f6b8e","#2f6c8e","#2e6d8e","#2e6e8e","#2e6f8e","#2d708e","#2d718e","#2c718e","#2c728e","#2c738e","#2b748e","#2b758e","#2a768e","#2a778e","#2a788e","#29798e","#297a8e","#297b8e","#287c8e","#287d8e","#277e8e","#277f8e","#27808e","#26818e","#26828e","#26828e","#25838e","#25848e","#25858e","#24868e","#24878e","#23888e","#23898e","#238a8d","#228b8d","#228c8d","#228d8d","#218e8d","#218f8d","#21908d","#21918c","#20928c","#20928c","#20938c","#1f948c","#1f958b","#1f968b","#1f978b","#1f988b","#1f998a","#1f9a8a","#1e9b8a","#1e9c89","#1e9d89","#1f9e89","#1f9f88","#1fa088","#1fa188","#1fa187","#1fa287","#20a386","#20a486","#21a585","#21a685","#22a785","#22a884","#23a983","#24aa83","#25ab82","#25ac82","#26ad81","#27ad81","#28ae80","#29af7f","#2ab07f","#2cb17e","#2db27d","#2eb37c","#2fb47c","#31b57b","#32b67a","#34b679","#35b779","#37b878","#38b977","#3aba76","#3bbb75","#3dbc74","#3fbc73","#40bd72","#42be71","#44bf70","#46c06f","#48c16e","#4ac16d","#4cc26c","#4ec36b","#50c46a","#52c569","#54c568","#56c667","#58c765","#5ac864","#5cc863","#5ec962","#60ca60","#63cb5f","#65cb5e","#67cc5c","#69cd5b","#6ccd5a","#6ece58","#70cf57","#73d056","#75d054","#77d153","#7ad151","#7cd250","#7fd34e","#81d34d","#84d44b","#86d549","#89d548","#8bd646","#8ed645","#90d743","#93d741","#95d840","#98d83e","#9bd93c","#9dd93b","#a0da39","#a2da37","#a5db36","#a8db34","#aadc32","#addc30","#b0dd2f","#b2dd2d","#b5de2b","#b8de29","#bade28","#bddf26","#c0df25","#c2df23","#c5e021","#c8e020","#cae11f","#cde11d","#d0e11c","#d2e21b","#d5e21a","#d8e219","#dae319","#dde318","#dfe318","#e2e418","#e5e419","#e7e419","#eae51a","#ece51b","#efe51c","#f1e51d","#f4e61e","#f6e620","#f8e621","#fbe723","#fde725"];

var svg1 = d3.select("#map1")
            .append("svg")
            .attr("height", h)
            .attr("width", w);

var svg2 = d3.select("#map2")
            .append("svg")
            .attr("height", h)
            .attr("width", w);

var path = d3.geo.path()
                 .projection(projection);

var hexbin = d3.hexbin()
                .size([w, h])
                .radius(3.5);

// first of two scales for linear fill 
// tip from SO: http://stackoverflow.com/questions/17671252/d3-create-a-continous-color-scale-with-many-strings-inputs-for-the-range-and-dy
var fill_scale1 = d3.scale.linear()
           .domain(d3.range(0, 1, 1.0 / (viridis_colors.length - 1)))
           .range(viridis_colors);

// declare basemap first to render before (i.e. below) points or hexbins 
var basemap1 = svg1.append("g");
var points = svg1.append("g");
var basemap2 = svg2.append("g");
var hex = svg2.append("g").attr("clip-path", "url(#map_clip)");

// GeoJSON file is modified from the Crime & Safety (2010-2012) - Shape.geojson file available at https://data.baltimorecity.gov/Neighborhoods/Crime-Safety-2010-2012-Shape/bywi-mtiu
// neighborhood data from original file replaced with number of vacant buildings ('see R analysis')  

var map = d3.json("/data/Baltimore_vacant_buildings_Shape.geojson", function(json) {


    // basemap for point plot 
    basemap1.selectAll("path")
       .data(json.features)
       .enter()
       .append("path")
       .attr("d", path) 
       .attr("stroke", "grey")
       .attr("fill", "white")
       .on("mouseover", function(d){

           d3.select(this)
             .attr("fill", "rgb(243, 100, 42)");

            d3.select("#tooltip")
              .select("#neighborhood")
              .text(d.properties.csa); 

            d3.select("#tooltip")
              .select("#datum")
              .text(function() {
                  var count = parseFloat(d.properties.vacant_buildings);
                  return comma_format(count) + " vacant buildings"; 
              });
        })
       .on("mouseout", function() {

           d3.select(this)
             .transition()
             .duration(50)
             .attr("fill", "white");

            d3.select("#tooltip")
              .select("#neighborhood")
              .text("\u00A0");  // Unicode equivalent of HTML &nbsp

            d3.select("#tooltip")
              .select("#datum")
              .text("\u00A0");
        });

    // clippling mask for hexbin plot
    var dims = path.bounds(json);
    var clip_w = dims[1][0] - dims[0][0];
    var clip_h = dims[1][1] - dims[0][1];

    svg2.append("clipPath")
        .attr("id", "map_clip")
        .append("rect")
        .attr("width", clip_w)
        .attr("height", 700)
        .attr("transform", function() {
            return "translate(" + 50 + "," + 29 +  ")";
        });
   
    // basemap for hexbin plot
    basemap2.selectAll("path")
       .data(json.features)
       .enter()
       .append("path")
       .attr("d", path) 
       .attr("stroke", "grey")
       .attr("fill", "#595959");
});

var vacancy = d3.csv("/data/Baltimore_vacant_buildings.csv", function(data) {
               
    // convert lat/lng string to numeric
    data.forEach(function(d) {
        d.latitude = +d.latitude;
        d.longitude = +d.longitude;
    });

    // plot points
    points.selectAll("circle")
       .data(data)
       .enter()
       .append("circle")
       .attr("cx", function(d) {
           return projection([d.latitude, d.longitude])[0]; })  // project lat
       .attr("cy", function(d) {
           return projection([d.latitude, d.longitude])[1]; })  // project lng
       .attr("r", 1)
       .attr("fill", "black")
       .style("opacity", 0.35)
       .style("pointer-events", "none");

    points2 = [];
    data.forEach(function(d) {
        d.latitude = +d.latitude;
        d.longitude = +d.longitude;
        var x = projection([d.latitude, d.longitude])[0];
        var y = projection([d.latitude, d.longitude])[1];
        points2.push([x, y]);
        });

    var bins = hexbin(points2);     // bin lat/lng
    var bins_n = [];                // points per hexbin  
    bins.forEach(function(d) {
        bins_n.push(d.length); 
    });

    // second of two scales for linear fill color
    var extent = d3.extent(bins_n);
    var fill_scale2 = d3.scale.linear()
               .domain([extent[0], extent[1]])
               .range([0,1]);

    hex.selectAll(".hexagon")
        .data(hexbin(points2)) 
        .enter()
        .append("path")
        .attr("class", "hexagon")
        .attr("d", hexbin.hexagon())
        .attr("transform", function(d) { 
                return "translate(" + d.x + "," + d.y + ")"; 
        })
        .style("fill", function(d) {
                return fill_scale1(fill_scale2(d.length));
        });
});