var svg;
var selection_mode = 0;
var previous_mode = 2;
var map_point = [[-1, -1]], map_line_x1 = -1, map_line_y1 = -1,
  map_line_x2 = -1, map_line_y2 = -1;

var r1 = 0, r2 = 0;
var dragged = false;


  var hours = [];
  for (var i = 0; i < 24; i++) {
    hours[i] = i;
  }

var filter_set1 = new Set();
var filter_set2 = new Set();
var filter_set3 = new Set();
var json_data = [];
var resolution_set = ["CLEARED-CONTACT JUVENILE FOR MORE INFO","COMPLAINANT REFUSES TO PROSECUTE","NONE", "ARREST, BOOKED","EXCEPTIONAL CLEARANCE","NOT PROSECUTED","JUVENILE BOOKED","UNFOUNDED",
"ARREST, CITED","LOCATED","PSYCHOPATHIC CASE"];

var category_set = new Set();

var day_of_week_set = ["Sunday", "Monday", "Tuesday", "Wednesday",
                         "Thursday", "Friday", "Saturday"];

var temp_g;
var temp_frequency1;

var g1, g2, g3;
var f1 = [];
var f2 = [];
var f3 = [];

var x1, y1, x2, y2, x3, y3;

var projection = d3.geo.mercator()
	.center([-122.433701, 37.767683]) // San Francisco, roughly
	.scale(225000)
	.translate([750 / 2, 750 / 2]);

var update4 = function(data) {
   var circles = svg.selectAll("circle").data(data);
   
   circles.enter()
     .append("circle")
     .attr("cx", function(d) { return projection(d.Location)[0]; })
     .attr("cy", function(d) { return projection(d.Location)[1]; })
     .attr("r", 1)
     .style("stroke", "black")
     .style("fill", "red")
     .style("opacity", 0.2);

  circles.exit().remove();

  // update frequency graph 1, 2, 3
  var frequency = [];
  var x = 0;
  for (let day_of_week of day_of_week_set) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(data
              .filter(function(d) { return d.DayOfWeek == day_of_week;})
              .map( function(d) { return 1;}));
    temp_frequency['d'] = day_of_week;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "Orange";
    x = x + 1;
  }
  temp_frequency1 = frequency.concat(f1);

   temp_g = g1.selectAll(".bar")
      .data(frequency.concat(f1));
    temp_g.enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x1(d.d); })
      .attr("width", x1.rangeBand())
      .attr("y", function(d) { return y1(d.f); })
      .attr("height", function(d) { return 200 - y1(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5)
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
                if (!dragged) return d.c;
                if (d.c == "Orange")
                  d.c = "Red"
                else if (d.c == "Red")
                  d.c = "Orange"
                else if (d.c == "steelblue")
                  d.c = "LightSkyBlue"
                else
                  d.c = "steelblue";
                return d.c;
            });
        });


   temp_g.attr("class", "bar")
      .attr("x", function(d) { return x1(d.d); })
      .attr("width", x1.rangeBand())
      .attr("y", function(d) { return y1(d.f); })
      .attr("height", function(d) { return 200 - y1(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5);

  var frequency = [];
  var x = 0;
  for (let hour of hours) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(data
              .filter(function(d) { return d.h == hour;})
              .map( function(d) { return 1;}));
    temp_frequency['h'] = hour;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "Orange";
    x = x + 1;
  }
  temp_frequency2 = frequency.concat(f2);

   temp_g = g2.selectAll(".bar")
      .data(frequency.concat(f2));
    temp_g.enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x2(d.h); })
      .attr("width", x2.rangeBand())
      .attr("y", function(d) { return y2(d.f); })
      .attr("height", function(d) { return 200 - y2(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5)
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
                if (!dragged) return d.c;
                if (d.c == "Orange")
                  d.c = "Red"
                else if (d.c == "Red")
                  d.c = "Orange"
                else if (d.c == "steelblue")
                  d.c = "LightSkyBlue"
                else
                  d.c = "steelblue";
                return d.c;
            });
        });

   temp_g.attr("class", "bar")
      .attr("x", function(d) { return x2(d.h); })
      .attr("width", x2.rangeBand())
      .attr("y", function(d) { return y2(d.f); })
      .attr("height", function(d) { return 200 - y2(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5);

  var frequency = [];
  var x = 0;
  for (let s of resolution_set) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(data
              .filter(function(d) { return d.Resolution == s;})
              .map( function(d) { return 1;}));
    temp_frequency['r'] = s;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "Orange";
    x = x + 1;
  }

  for (let f of frequency) {
    f['f'] = d3.scale.log()(f['f'] + 1);
  }


  temp_frequency3 = frequency.concat(f3);

   temp_g = g3.selectAll(".bar")
      .data(frequency.concat(f3));
    temp_g.enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x3(d.r); })
      .attr("width", x3.rangeBand())
      .attr("y", function(d) { return y3(d.f); })
      .attr("height", function(d) { return 200 - y3(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5)
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
                if (!dragged) return d.c;
                if (d.c == "Orange")
                  d.c = "Red"
                else if (d.c == "Red")
                  d.c = "Orange"
                else if (d.c == "steelblue")
                  d.c = "LightSkyBlue"
                else
                  d.c = "steelblue";
                return d.c;
            });
        });

   temp_g.attr("class", "bar")
      .attr("x", function(d) { return x3(d.r); })
      .attr("width", x3.rangeBand())
      .attr("y", function(d) { return y3(d.f); })
      .attr("height", function(d) { return 200 - y3(d.f); })
      .attr("fill", function(d) { return d.c;})
      .attr("opacity", 0.5);

   //temp_g.exit().remove();

};

var update3 = function(data) {
  data = json_data;
  filter_set1 = new Set();
  filter_set2 = new Set();
  filter_set3 = new Set();    
  f1.forEach(function(d) { if (d.c != "LightSkyBlue") filter_set1.add(d.d)});  
 f2.forEach(function(d) { if (d.c != "LightSkyBlue") filter_set2.add(d.h)});
 f3.forEach(function(d) { if (d.c != "LightSkyBlue") filter_set3.add(d.r)});
  data = data.filter(function(d) { 

     var temp_d = d.DayOfWeek;
     var temp_h = d.h;
     var temp_r = d.Resolution;
   return (
     (filter_set1.has(temp_d) || filter_set1.size == 0)
   && (filter_set2.has(temp_h) || filter_set2.size == 0)
   && (filter_set3.has(temp_r) || filter_set3.size == 0) &&
     ((d3.geo.distance(d.Location, projection.invert([map_line_x1, map_line_y1])) <= r1 / 3925.2) || map_line_x1 == -1)
   &&  ((d3.geo.distance(d.Location, projection.invert([map_line_x2, map_line_y2])) <= r2 / 3925.2) || map_line_x2 == -1)
    )});
  update4(data);
};


d3.json("data/scpd_incidents.json", function(error, data) {
  // This function gets called when the request is resolved (either failed or succeeded)

  if (error) {
    // Handle error if there is any
    return console.warn(error);
  }

  preprocess(data.data);
  // If there is no error, then data is actually ready to use
  initialize(data.data);
  setInterval(update3, 100);
});

function preprocess(data) {
  data.forEach(function(d) {
    var time_formatter = d3.time.format('%H:%M');
    var time_object = time_formatter.parse(d.Time);
    d['h'] =  time_object.getHours();
  });
  json_data = data;
};

function initialize(data) {

  //initializing
  var width = 820,
	height = 800;

  var margin = {top: 20, right: 20, bottom: 30, left: 50},
  w = width - margin.left -  margin.right,
  h = height - margin.top - margin.bottom;
 
  var width1 = 500,
  height1 = 200;

  var day_of_week_set = ["Sunday", "Monday", "Tuesday", "Wednesday",
                         "Thursday", "Friday", "Saturday"];

 var drag = d3.behavior.drag()
    .on("dragstart", function() { dragged = true;console.log(dragged); })
    .on("dragend", function() { dragged = false; });

 
  data.forEach(function(d) {
   category_set.add(d.Category);
  });


  //console.log(category_set);
  //console.log(resolution_set);
  //console.log(day_of_week_set);

  // Set up projection that map is using
  // This is the mapping between <longitude, latitude> position to <x, y> pixel position on the map
  // projection([lon, lat]) returns [x, y]
  // projection.invert([x, y]) returns [lon, lat]

  // Add an svg element to the DOM
  svg = d3.select("body").append("svg")
	.attr("width", width + width1 + 150)
	.attr("height", height + 200)
	.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  // Add svg map at correct size, assumes map is saved in a subdirectory called "data"
  svg.append("image")
          .attr("width", w)
          .attr("height", h)
          .attr("xlink:href", "data/sf-map.svg");

  var circles = svg.selectAll("circle").data(data);

  circles.enter()
     .append("circle")
     .attr("cx", function(d) { return projection(d.Location)[0]; })
     .attr("cy", function(d) { return projection(d.Location)[1]; })
     .attr("r", 1)
     .style("stroke", "black")
     .style("fill", "red")
     .style("opacity", 0.2);

  circles.exit()
     .style("fill", "grey");

  // beginning of the bar chart

  var frequency = [];
  var x = 0;
  for (let day_of_week of day_of_week_set) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(svg.selectAll("circle").data()
              .filter(function(d) { return d.DayOfWeek == day_of_week;})
              .map( function(d) { return 1;}));
    temp_frequency['d'] = day_of_week;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "LightSkyBlue";
    x = x + 1;
  }
  //console.log(frequency);

  // set up frequency graph
  x1 = d3.scale.ordinal()
          .rangeRoundBands([20, width1], .1);

  x1.domain(frequency.map( function(d) {return d.d}))

  var xAxis = d3.svg.axis()
          .scale(x1)
          .orient("bottom");

  y1 = d3.scale.linear()
         .range([height1, 20])

  y1.domain([0, d3.max(frequency, function(d) { return d.f; })]);

  var yAxis = d3.svg.axis()
        .scale(y1)
        .orient("left"); 

  g1 = svg.append("g")
        .attr("transform", "translate(" + (margin.left + w) + ", 0)");

   // show frequency
   g1.selectAll(".bar")
      .data(frequency)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x1(d.d); })
      .attr("width", x1.rangeBand())
      .attr("y", function(d) { return y1(d.f); })
      .attr("height", function(d) { return height1 - y1(d.f); })
      .attr("fill", "LightSkyBlue")
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
                if (!dragged) return d.c;
                if (d.c == "LightSkyBlue")
                  d.c = "steelBlue"
                else d.c ="LightSkyBlue";
                return d.c;
            });
        });


   // draw axises.

   g1.call(drag);

   g1.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height1 + ")")
    .call(xAxis)
    .append("text")
    .attr("class", "label")
    .attr("x", width1)
    .attr("y", -6)
    .style("text-anchor", "end")
    .text("Day of the week");

   g1.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("class", "label")
    .attr("transform", "rotate(-90)")
    .attr("y", 20)
    .style("text-anchor", "end")
    .text("Crime Number"); 

  f1 = frequency;

  // end of the bar chart


  // beginning of the bar chart2

  var width2 = 500;
  var height2 = 200;

  var frequency = [];
  var x = 0;
  for (let hour of hours) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(svg.selectAll("circle").data()
              .filter(function(d) { return d.h == hour;})
              .map( function(d) { return 1;}));
    temp_frequency['h'] = hour;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "LightSkyBlue";
    x = x + 1;
  }
  //console.log(frequency);

  // set up frequency graph
  x2 = d3.scale.ordinal()
          .rangeRoundBands([20, width2], .1);

  x2.domain(frequency.map( function(d) {return d.h}))

  var xAxis = d3.svg.axis()
          .scale(x2)
          .orient("bottom");

  y2 = d3.scale.linear()
         .range([height2, 0])

  y2.domain([0, d3.max(frequency, function(d) { return d.f; })]);

  var yAxis = d3.svg.axis()
         .scale(y2)
        .orient("left"); 

  g2 = svg.append("g")
        .attr("transform", "translate(" + (margin.left + w) + "," + (margin.top + height1 + margin.bottom) + ")");

   // show frequency
   g2.selectAll(".bar")
      .data(frequency)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x2(d.h); })
      .attr("width", x2.rangeBand())
      .attr("y", function(d) { return y2(d.f); })
      .attr("height", function(d) { return height1 - y2(d.f); })
      .attr("fill", "LightSkyBlue")
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
 if (!dragged) return d.c;
                if (d.c == "LightSkyBlue")
                  d.c = "steelBlue"
                else d.c ="LightSkyBlue";
                return d.c;
            });
        });

   // draw axises.

   g2.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height2 + ")")
    .call(xAxis)
    .append("text")
    .attr("class", "label")
    .attr("x", width2)
    .attr("y", -6)
    .style("text-anchor", "end")
    .text("Time of the day");

   g2.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("class", "label")
    .attr("transform", "rotate(-90)")
    .attr("y", 20)
    .style("text-anchor", "end")
    .text("Crime Number"); 

  f2 = frequency;

  // end of the bar chart2


  
  // beginning of the bar chart3

  var width3 = 500;
  var height3 = 200;

  var frequency = [];
  var x = 0;
  for (let s of resolution_set) {
    var temp_frequency = new Map();
    //console.log(svg.selectAll("circle").data()
    //          .filter(function(d) { return d.DayOfWeek == day_of_week;}));
    temp_frequency['f'] = d3.sum(svg.selectAll("circle").data()
              .filter(function(d) { return d.Resolution == s;})
              .map( function(d) { return 1;}));
    temp_frequency['r'] = s;
    frequency[x] = temp_frequency;
    temp_frequency['c'] = "LightSkyBlue";
    x = x + 1;
  }
  //console.log(frequency);

  for (let f of frequency) {
    f['f'] = d3.scale.log()(f['f'] + 1);
  }

  // set up frequency graph
  x3 = d3.scale.ordinal()
          .rangeRoundBands([20, width3], .1);

  x3.domain(frequency.map( function(d) {return d.r}))

  var xAxis = d3.svg.axis()
          .scale(x3)
          .orient("bottom");

  y3 = d3.scale.linear()
         .range([height3, 0])

  y3.domain([0, d3.max(frequency, function(d) { return d.f; })]);

  var yAxis = d3.svg.axis()
         .scale(y3)
        .orient("left"); 

  g3 = svg.append("g")
        .attr("transform", "translate(" + (margin.left + w) + "," + (margin.top + height1 + height2 + 2 * margin.bottom) + ")");

   // show frequency
   g3.selectAll(".bar")
      .data(frequency)
    .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x3(d.r); })
      .attr("width", x3.rangeBand())
      .attr("y", function(d) { return y3(d.f); })
      .attr("height", function(d) { return height3 - y3(d.f); })
      .attr("fill", "LightSkyBlue")
      .on("mouseover", function(d, i) {
            d3.select(this).attr("fill", function(d) {
 if (!dragged) return d.c;
                if (d.c == "LightSkyBlue")
                  d.c = "steelBlue"
                else d.c ="LightSkyBlue";
                return d.c;
            });
        });


   // draw axises.

   var x_axis = g3.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height3 + ")")
    .call(xAxis);
    
   x_axis.selectAll("text")
    .attr("y", 0)
    .attr("x", 9)
    .attr("dy", ".35em")
    .attr("transform", "rotate(45)")
    .style("text-anchor", "start");

  x_axis.append("text")
    .attr("class", "label")
    .attr("x", width3)
    .attr("y", -6)
    .style("text-anchor", "end")
    .text("Resolution Type");


   g3.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("class", "label")
    .attr("transform", "rotate(-90)")
    .attr("y", 20)
    .style("text-anchor", "end")
    .text("Crime Number Log 10"); 

  f3 = frequency;

  // end of the bar chart2

  g3.call(drag);

  var point1 = {};
  var point2 = {};

   svg.selectAll("text.map_point")
                .data(map_point)
                .enter()
                .append("text")
                .attr("class", "map_point")
                .text(function(d) 
                  {
                    if (d[1] != -1) {
                    return " " + d[0] + ", " + d[1]; }
                  } 
                )
                .attr("x", 440)
                .attr("y", 750)
                .attr("fill", "grey");

   var delay = 250;

  svg.on("mousemove", function() {
          var coords = d3.mouse(this);

          newData= {
            x: Math.round( coords[0]),  // Takes the pixel number to convert to number
            y: Math.round( coords[1])
          };

          if (function (x, y) {
  return y <= 20 + 750 && y > 20 && x <= 50 + 750 && x > 50;
}(newData.x, newData.y)) {
               loc = projection.invert([newData.x, newData.y]);
               if (selection_mode == 2) return;
               if (selection_mode == 0) {
                 map_line_x1 = newData.x;
                 map_line_y1 = newData.y;
               } else {
                 map_line_x2 = newData.x;
                 map_line_y2 = newData.y;
               }
          }
   });


 var dblclick_timer = false;
 svg.on("click", function() {
    // if double click timer is active, this click is the double click
    if ( dblclick_timer )
    {
        clearTimeout(dblclick_timer);
        dblclick_timer = false;
        // double click code code comes here

          if (function (x, y) {
  return y <= 20 + 750 && y > 20 && x <= 50 + 750 && x > 50;
  }(newData.x, newData.y)) {
             previous_mode = 1 - selection_mode;
             selection_mode = 2;

          }
        console.log("double_clicked");
    }
    // otherwise, what to do after single click (double click has timed out)
    else dblclick_timer = setTimeout( function(){
        dblclick_timer = false
        // single click code code comes here
        

          console.log("clicked!");

          if (function (x, y) {
  return y <= 20 + 750 && y > 20 && x <= 50 + 750 && x > 50;
 }(newData.x, newData.y)) {
             if (selection_mode == 2) {
              selection_mode = previous_mode;
            }
          }

    }, 300)
})


  d3.select('#position').append('text')
    .text('');
 
  g2.call(drag);
 
};

var update = function () {
   // update map_point..
    if (selection_mode == 2) return;

 var projection = d3.geo.mercator()
        .center([-122.433701, 37.767683]) // San Francisco, roughly
        .scale(225000)
        .translate([750 / 2, 750 / 2]);


    d3.select("#selection_line1").transition().duration(5)
     .ease('cubic_in_out').style('left', (map_line_x1 + 10) + 'px')
     .style('opacity', 1 - selection_mode * 0.4);

     d3.select("#selection_line2").transition().duration(5)
     .ease('cubic_in_out').style('top', (map_line_y1 + 10) + 'px')
     .style('opacity', 1 - selection_mode * 0.4);

    d3.select("#selection_line3").transition().duration(5)
     .ease('cubic_in_out').style('left', (map_line_x2 + 10) + 'px')
     .style('opacity', 0.6 + selection_mode * 0.4);

     d3.select("#selection_line4").transition().duration(5)
     .ease('cubic_in_out').style('top', (map_line_y2 + 10) + 'px')
     .style('opacity', 0.6 + selection_mode * 0.4);
   
     loc = projection.invert([map_line_x1, map_line_x2]);

     d3.select('#position').select('text').text(' ' + loc[0]
     + ', ' + loc[1]);
};

setInterval(update, 100);

var update2 = function() {
  var radius1 = 0;
  var radius2 = 0;
  if (selection_mode != 0) {
    r1 = d3.select('#r1').node().value;
    radius1 = 150 * r1;
  }
  if (selection_mode == 2 && map_line_x2 > 0) {
    r2 = d3.select('#r2').node().value;
    radius2 = 150 * r2;
  }

     d3.select('#circle1').transition().duration(5).ease('cubic_in_out')
     .style('left', (map_line_x1 + 10 - radius1/2) + 'px').style('top', (map_line_y1 + 10 - radius1/2) + 'px')
     .style('width', radius1 + 'px')
     .style('height', radius1 + 'px');

  d3.select('#circle2').transition().duration(5).ease('cubic_in_out')
     .style('left', (map_line_x2 + 10 - radius2/2) + 'px').style('top', (map_line_y2 + 10 - radius2/2) + 'px')
     .style('width', radius2 + 'px')
     .style('height', radius2 + 'px');

 
};

setInterval(update2, 100);

