(function($){

	$.fn.phTreemap = function(options){
		var phTreemap = $.fn.phTreemap;

		var $dom = $(this),
			id = $dom.selector,
			parent = $(this).parent(),
			endpoint = $dom.data('url'),
			npi = $dom.data('npi'),
			entitytypecode = $dom.data('entitytype'),
			CHART_HEIGHT = $dom.data('height');
		CHART_HEIGHT = (CHART_HEIGHT === undefined ? 600 : CHART_HEIGHT);
		$(id).append(
				'<div class="panel-heading">'
				+'<h4 id="marketmapheader"></h4>'
				+'</div>'
				+'<div class="panel-body">'
				+'<div id="tabs">'
				+'<ul class="nav nav-tabs">'
				+'<li class="active"><a id="splittersTab" data-toggle="tab" href="#splittersChart">Splitters</a></li>'
				+'<li class=""><a id="allPhysiciansTab" data-toggle="tab" href="#allPhysiciansChart">All Physicians</a></li>'
				+'<li><a id="loyalistsTab" data-toggle="tab" href="#loyalistsChart">Loyalists</a></li>'
				+'<a id="report" class="btn btn-default btn-med disabled pull-right">Generate Report</a>'
				+'</ul>'
				+'</div>'
				+'<div class="tab-content">'
				+'<div id="splittersChart" class="tab-pane fade in active"></div>'
				+'<div id="allPhysiciansChart" class="tab-pane fade">'
				+'</div>'
				+'<div id="loyalistsChart" class="tab-pane fade">'
				+'</div>'
				+'<div id="communityChart" class="tab-pane fade"></div>'
				+'</div>'
				+'</div>'
				+'<div id="legend"></div>'
        )

		String.prototype.capitalize = function(all){
		  if(all){
		    return this.split(' ').map(function(e){return e.capitalize();}).join(' ');    
		  }else{
		    return this.charAt(0).toUpperCase() + this.slice(1).toLowerCase();
		  } 
		}

		var activateTab = function(tab_){
		  $('.nav-tabs a[href="#' + tab_ + '"]').tab('show');
		};

		document.onkeydown = function(e) {
		  switch (e.keyCode) {
		    case 37:
		      if ($('#loyalistsChart').hasClass("active")){
		        activateTab("allPhysiciansChart");
		      } else if ($('#splittersChart').hasClass("active")){
		        activateTab("loyalistsChart")
		      }
		      break;
		    case 39:
		      if ($('#allPhysiciansChart').hasClass("active")){
		        activateTab("loyalistsChart");
		      } else if ($('#loyalistsChart').hasClass("active")){
		        activateTab("splittersChart");
		      }
		      break;
		  }
		};

		$(".btn-group > .btn").click(function(){
		  $(this).addClass("active").siblings().removeClass("active");
		});

		var dataAll, splitters, initialized, filter, drillDown,
		    graphName = "allPhysicians", 
		    splitterCount = 0, allPhysiciansReportData, loyalistsReportData, splittersReportData, reportData
		var formatNumber = d3.format(",d");

		var allPhysiciansMapHasChildren = loyalistsMapHasChildren = splittersMapHasChildren = true;

		var initialValue = "";
		var allBreadcrumbs = loyalistBreadcrumbs = splitterBreadcrumbs = initialValue;

		$('.grandparent').hide();

		var mousemove = function(d) {
		  var xPosition = (d3.event.pageX > 450 ? d3.event.pageX - 220 : d3.event.pageX + 5);
		  var yPosition = d3.event.pageY - 55;

		  d3.select("#tooltip")
		    .style("left", xPosition + "px")
		    .style("top", yPosition + "px");
		  d3.select("#tooltip #heading")
		    .text(d.name);
		  d3.select("#tooltip #visits")
		    .text("Visits: " + formatNumber(d.value));
		  // d3.select("#tooltip #otherinfo")
		  //   .text("test");
		  d3.select("#tooltip").classed("hidden", false);
		};

		var mouseout = function() {
		  d3.select("#tooltip").classed("hidden", true);
		};

		var build = function(root){
		$('#report').on('click', function(){
		    var filter, chartType;
		    if ($('#loyalistsChart').hasClass("active")){
		      reportData = loyalistsReportData;
		      filter = $('#loyalistsChart').find('svg > g').find('.grandparent')[0].textContent.split(" > ");
		      chartType = "Loyalists_";
		    } else if ($('#allPhysiciansChart').hasClass("active")){
		      reportData = allPhysiciansReportData;
		      filter = $('#allPhysiciansChart').find('svg > g').find('.grandparent')[0].textContent.split(" > ");
		      chartType = "AllPhysicians_";
		    } else if ($('#splittersChart').hasClass("active")){
		      reportData = splittersReportData;
		      filter = $('#splittersChart').find('svg > g').find('.grandparent')[0].textContent.split(" > ");
		      chartType = "splitters_";
		    }

		    var drillDown = filter.length-1;
		    var title = filter[drillDown];
		    var nonSpecialists;// = (title.indexOf("(non-specialists)") > -1);
		    var level;
		    for (var i=0;i<filter.length;i++){
		      if (filter[i].indexOf("non-specialists")>-1){
		        nonSpecialists = true;
		      }
		    }

		    if (drillDown == 0){
		      level = "Market Map";
		    } else if (drillDown == 1){
		      level = "Taxonomy";
		    } else if (drillDown == 2){
		      level = "Classification";
		    } else if (drillDown == 4 || nonSpecialists){
		      level = "Provider Name";
		    } else if (drillDown == 3){
		      level = "Specialization";
		    } 

		    var generateReport = [];

		    if (title == "Market Map"){
		      generateReport = reportData;
		    } else {
		      for (var i = 0; i < reportData.length; i++){
		        if (reportData[i][level] == title){
		          generateReport.push(reportData[i])
		        }
		      }
		    }
		    title = chartType + filter[drillDown];
		    JSONToCSVConvertor(generateReport, title, true);
		  });

		  allPhysiciansReportData = _.sortBy(root.nodes, 'Share').reverse();

		  splittersReportData = [];
		  loyalistsReportData = [];
		  for (var i = 0; i < allPhysiciansReportData.length; i++){
		    var visitsToSelected = allPhysiciansReportData[i]["Visits to hospital"];
		    var visitsToOther = allPhysiciansReportData[i]["Visits to other General Acute Hospitals"];
		    var totalVisits = visitsToOther + visitsToSelected;
		    var leakage = (visitsToOther/totalVisits)*100
		    var percentCaptured = 100 - leakage;
		    if (leakage <= 25 && percentCaptured >= 75){
		      loyalistsReportData.push(allPhysiciansReportData[i])
		    } else if (leakage < 75){
		      splittersReportData.push(allPhysiciansReportData[i])
		    }
		  }

		  splitters = JSON.parse(root.splitters);
		  loyaliststree = JSON.parse(root.loyalists);
		  root = JSON.parse(root.allDocs);
		  // dataAll = root;

		  phTreemap.buildTreemap = function(data, id) {

		  	var margin = {top:25, right: 0, bottom: 0, left: 0},
			    width = parent.width() - margin.top,
			    height = CHART_HEIGHT,// - margin.top - margin.bottom,
			    transitioning;

		      var mousemove = function(d) {
		        var xPosition = d3.event.pageX - 220;
		        var yPosition = d3.event.pageY - 55;

		        d3.select("#tooltip")
		          .style("left", xPosition + "px")
		          .style("top", yPosition + "px");
		        d3.select("#tooltip #heading")
		          //.html("<strong>"+d.name+"</strong>");
		          .html(function(){
		            if (d._children){
		              return "<strong>"+d.name+"</strong>";
		            } else {
		              return "<strong>"+d.parent.name+"</strong>";
		            }
		          })
		        d3.select("#tooltip #visits")
		          .html(function(){
		            if (d._children){
		              return "<strong>Visits:</strong> "+formatNumber(d.value)+"</br><strong>Percent captured:</strong> "+(threshold(d, "html")[1] * 100).toFixed(2) + "%";
		            } else {
		              if (d.name.indexOf("to other hospitals") > -1){
		                var leakage = d.value/d.total;
		                var captured = 1 - leakage;
		                return "<strong>Visits:</strong> "+formatNumber(d.total - d.value)+"</br><strong>Visits to other hospitals:</strong> "+formatNumber(d.value)+"</br><strong>Percent Captured:</strong> "+(captured*100).toFixed(2)+"%"+"</br><strong>Leakage:</strong> "+(leakage*100).toFixed(2)+"%";
		              } else {
		                var leakage = d.value/d.total;
		                var captured = 1 - leakage;
		                return "<strong>Visits:</strong> "+formatNumber(d.value)+"</br><strong>Visits to other hospitals:</strong> "+formatNumber(d.total-d.value)+"</br><strong>Percent Captured:</strong> "+(leakage*100).toFixed(2)+"%"+"</br><strong>Leakage:</strong> "+(captured*100).toFixed(2)+"%";
		              }
		            }
		          })
		        // d3.select("#tooltip #otherinfo")
		        //   .text("test");
		        d3.select("#tooltip").classed("hidden", false);
		      };

		      var mouseout = function() {
		        d3.select("#tooltip").classed("hidden", true);
		      };

		    var x = d3.scale.linear()
		        .domain([0, width])
		        .range([0, width]);

		    var y = d3.scale.linear()
		        .domain([0, height])
		        .range([0, height]);

		    var treemap = d3.layout.treemap()
		        .children(function(d, depth) { return depth ? null : d._children; })
		        .sort(function(a, b) { 
		          return a.value - b.value;
		        })
		        .ratio(height / width * 0.5 * (1 + Math.sqrt(5)))
		        .round(false);

		    var svg = d3.select(id).append("svg")
		        .attr("width", width)
		        .attr("height", height + margin.top)
		        .style("margin-left", -margin.left + "px")
		        .style("margin-right", -margin.right + "px")
		      .append("g")
		        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
		        .style("shape-rendering", "crispEdges")
		        .style("opacity", 0);;

		    var grandparent = svg.append("g")
		        .attr("class", "grandparent");

		    grandparent.append("rect")
		        .attr("y", -margin.top)
		        .attr("width", width)
		        .attr("height", margin.top);

		    grandparent.append("text")
		        .attr("x", 6)
		        .attr("y", 6 - margin.top)
		        .attr("dy", ".75em");

		    svg
		      .transition()
		      .delay(400)
		      .duration(450)
		      .style("opacity", 1)

		    if (!initialized){
		      initialize(data);
		      accumulate(data);
		      layout(data);
		    }
		    display(data);

		      function initialize(root) {
		    root.x = root.y = 0;
		    root.dx = width;
		    root.dy = height;
		    root.depth = 0;
		  }

		  // Aggregate the values for internal nodes
		  function accumulate(d) {
		    return (d._children = d.children)
		        ? d.value = d.children.reduce(function(p, v) { return p + accumulate(v); }, 0)
		        : d.value;
		  }

		  // Compute the treemap layout recursively such that each group of siblings
		  // uses the same size (1×1) rather than the dimensions of the parent cell
		  function layout(d) {
		    if (d._children) {
		      treemap.nodes({_children: d._children});
		      d._children.forEach(function(c) {
		        c.x = d.x + c.x * d.dx;
		        c.y = d.y + c.y * d.dy;
		        c.dx *= d.dx;
		        c.dy *= d.dy;
		        c.parent = d;
		        layout(c);
		      });
		    }
		  }

		  function display(d) {
		    grandparent
		        .datum(d.parent)
		        .on("click", transition)
		      .select("text")
		        .text(name(d));

		    var g1 = svg.insert("g", ".grandparent")
		        .datum(d)
		        .attr("class", "depth");

		    var g = g1.selectAll("g")
		        .data(d._children)
		      .enter().append("g");

		    g.filter(function(d) { return d._children; })
		        .classed("children", true)
		        .on("click", transition);

		    g.selectAll(".child")
		        .data(function(d) { return d._children || [d]; })
		      .enter().append("rect")
		        .attr("class", "child")
		        .call(rect);

		    /* write parent rectangle */
		      g.append("rect")
		        .attr("class", "parent")
		        .on("mousemove", mousemove)
		        .on("mouseout", mouseout)
		        .call(rect)
		        .on("click", function(d) { 
		          if(!d._children){
		            var originUrl = location.origin;
		            var url = originUrl+d.url
		            // window.open(url, "_blank"); 
		          }
		        })
		        .append("data-tooltip")
		        .text(function(d) { return d.name + "\n" + formatNumber(d.value) + " visits"; }); 

		    /* Adding a foreign object instead of a text object, allows for text wrapping */
		      g.append("foreignObject")
		        .call(rect)
		        .on("mousemove", mousemove)
		        .on("mouseout", mouseout)
		        .attr("class","foreignobj")
		        .append("xhtml:div") 
		        .attr("dy", ".75em")
		        .html(function(d) {
		          var percentToSelected;
		          if (d._children == undefined){ 
		            percentToSelected = ((d.value/d.total)*100).toFixed(2) + "%";
		          } else {
		            percentToSelected = (threshold(d, "html")[1] * 100).toFixed(2) + "%";
		          }
		          return d.name + " | " + percentToSelected
		        })
		        .on("click", function(d) { 
		          if(!d._children){
		            var originUrl = location.origin;
		            var url = originUrl+d.url
		            window.open(url, "_blank"); 
		          }
		        })
		        .attr("class","textdiv");

		    function transition(d) {
		        if (transitioning || !d) return;
		        transitioning = true;

		        var g2 = display(d),
		        t1 = g1.transition().duration(750),
		        t2 = g2.transition().duration(750);

		        // Update the domain only after entering new elements.
		        x.domain([d.x, d.x + d.dx]);
		        y.domain([d.y, d.y + d.dy]);

		        // Enable anti-aliasing during the transition.
		        svg.style("shape-rendering", null);

		        // Draw child nodes on top of parent nodes.
		        svg.selectAll(".depth").sort(function(a, b) { return a.depth - b.depth; });

		        // Fade-in entering text.
		        g2.selectAll("text").style("fill-opacity", 0);
		        g2.selectAll("foreignObject div").style("display", "none"); /*added*/

		        // Transition to the new view.
		        t1.selectAll("text").call(text).style("fill-opacity", 0);
		        t2.selectAll("text").call(text).style("fill-opacity", 1);
		        t1.selectAll("rect").call(rect);
		        t2.selectAll("rect").call(rect);

		        t1.selectAll(".textdiv").style("display", "none"); /* added */
		        t1.selectAll(".foreignobj").call(foreign); /* added */
		        t2.selectAll(".textdiv").style("display", "block"); /* added */
		        t2.selectAll(".foreignobj").call(foreign); /* added */ 

		        // Remove the old node when the transition is finished.
		        t1.remove().each("end", function() {
		        svg.style("shape-rendering", "crispEdges");
		        transitioning = false;
		        });

		    }

		    return g;
		  }

		  function text(text) {
		    text.attr("x", function(d) { 
		      return x(d.x) + 6; })
		        .attr("y", function(d) { return y(d.y) + 6; });
		  }

		  function rect(rect) {
		    rect.attr("x", function(d) { return x(d.x); })
		        .attr("y", function(d) { return y(d.y); })
		        .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
		        .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); })
		        .style("fill", function(d){ return threshold(d, "fill")[0]})
		  }

		  function position() {
		    this.style("left", function(d) { return d.x + "px"; })
		        .style("top", function(d) { return d.y + "px"; })
		        .style("width", function(d) { return Math.max(0, d.dx - 2) + "px"; })
		        .style("height", function(d) { return Math.max(0, d.dy - 2) + "px"; });
		  }

		  function threshold(d, location) { // sart fill
		    var visitsToSelected = [];
		    var visitsToOther = [];
		    if (d.parent.name == 'Market Map'){ // fill for taxonomy nodes start
		      $.each(d._children, function(i,v){
		        if (v.name.indexOf("non-specialists") > -1){
		          $.each(v._children, function(i1, v1){
		            $.each(v1._children, function(i2, v2){
		              if (v2.name.indexOf("to other hospitals") > -1){
		                visitsToOther.push(v2.value)
		              } else {
		                visitsToSelected.push(v2.value)
		              }
		            })
		          })
		        } else { 
		          $.each(v._children, function(i1, v1){
		            if (v1._children == undefined){
		              if (v1.name.indexOf("to other hospitals") > -1){
		                visitsToOther.push(v1.value)
		              } else{
		                visitsToSelected.push(v1.value)
		              }
		            } else{
		              $.each(v1._children, function(i2, v2){
		                if (v2._children == undefined){
		                  if (v2.name.indexOf("to other hospitals") > -1){
		                    visitsToOther.push(v2.value)
		                  } else{
		                    visitsToSelected.push(v2.value)
		                  }
		                } else{
		                  $.each(v2._children, function(i3, v3){
		                    if (v3.name.indexOf("to other hospitals") > -1){
		                      visitsToOther.push(v3.value)
		                    } else{
		                      visitsToSelected.push(v3.value)
		                    }
		                  })
		                }
		              })
		            }
		          })
		        }
		      })
		    } // taxonomy nodes

		    else if (d.parent.parent.name == 'Market Map'){ // fill for classification nodes start
		      $.each(d._children, function(i,v){
		        if (v._children == undefined){
		          if (v.name.indexOf("to other hospitals") > -1){
		            visitsToOther.push(v.value)
		          } else {
		            visitsToSelected.push(v.value)
		          }
		        } else {
		          $.each(v._children, function(i2, v2){
		            if (v2._children == undefined){
		              if (v2.name.indexOf("to other hospitals") > -1){
		                visitsToOther.push(v2.value)
		              } else { 
		                visitsToSelected.push(v2.value)
		              }
		            } else {
		              $.each(v2._children, function(i3, v3){
		                if (v3.name.indexOf("to other hospitals") > -1){
		                  visitsToOther.push(v3.value)
		                } else { 
		                  visitsToSelected.push(v3.value)
		                }
		              })
		            }
		          })
		        }
		      })
		    } // end classification nodes

		    else if (d.parent.parent.parent.name == 'Market Map'){ // fill specialization nodes start
		      if (d._children == undefined){
		        if (d.name.indexOf("to other hospitals") > -1){
		          visitsToOther.push(d.value)
		        } else {
		          visitsToSelected.push(d.value)
		        }
		      } else {
		        $.each(d._children, function(i, v){
		          if (v._children == undefined){
		            if (v.name.indexOf("to other hospitals") > -1){
		              visitsToOther.push(v.value)
		            } else {
		              visitsToSelected.push(v.value)
		            }
		          } else {
		            $.each(v._children, function(i1, v1){
		              if (v1.name.indexOf("to other hospitals") > -1){
		                visitsToOther.push(v1.value)
		              } else {
		                visitsToSelected.push(v1.value)
		              }
		            })
		          }
		        })
		      }
		    } // specialization nodes end

		    else if (d.parent.parent.parent.parent.name == 'Market Map'){ // provider nodes start
		      if (d._children == undefined){
		        if (d.name.indexOf("to other hospitals") > -1){
		          visitsToOther.push(d.value)
		        }
		        else {
		          visitsToSelected.push(d.value)
		        }
		      } else {
		        $.each(d._children, function(i, v){
		          if (v.name.indexOf("to other hospitals") > -1){
		            visitsToOther.push(v.value)
		          }
		          else {
		            visitsToSelected.push(v.value)
		          }
		        })
		      }
		    } // provider nodes end

		    else if (d.parent.parent.parent.parent.parent.name == 'Market Map'){ // visit comparison nodes start
		      if (d.parent.parent.name.indexOf("non-specialists") == -1){
		        if (d.name.indexOf("to other hospitals") > -1){
		          visitsToOther.push(d.value)
		        } else {
		          visitsToSelected.push(d.value)
		        }
		      }
		    } //// visit comparison nodes end

		    var sumOfVisitsToSelected = d3.sum(visitsToSelected);
		    var sumOfVisitsToOther = d3.sum(visitsToOther);
		    percentCaptured = sumOfVisitsToSelected/(sumOfVisitsToOther+sumOfVisitsToSelected);

		    var leakageColorScale = {
		      loyalist: ["#337ab7", percentCaptured, d.total],
		      loyalist1: ["#63a0d4", percentCaptured, d.total],
		      loyalist2: ["#9fc5e5", percentCaptured, d.total],
		      loyalist3: ["#dbe9f5", percentCaptured, d.total],
		      leaker: ["#f9e2e2", percentCaptured, d.total],
		      leaker1: ["#f4cecd", percentCaptured, d.total],
		      leaker2: ["#e7908e", percentCaptured, d.total],
		      leaker3: ["#d9534f", percentCaptured, d.total]
		    }

		    if ((0.875 <= percentCaptured && percentCaptured <= 1) || percentCaptured > 1){  
		      return leakageColorScale.loyalist;
		    } else if (0.75 <= percentCaptured && percentCaptured < 0.875){
		      return leakageColorScale.loyalist1;
		    } else if (0.625 <= percentCaptured && percentCaptured < 0.75){
		      return leakageColorScale.loyalist2;
		    } else if (0.5 <= percentCaptured && percentCaptured < 0.625){
		      return leakageColorScale.loyalist3;
		    } else if (0.375 <= percentCaptured && percentCaptured < 0.5){
		      return leakageColorScale.leaker;
		    } else if (0.25 <= percentCaptured && percentCaptured < 0.375){
		      return leakageColorScale.leaker1;
		    } else if (0.125 <= percentCaptured && percentCaptured < 0.25){
		      return leakageColorScale.leaker2;
		    } else if (percentCaptured < 0.125){
		      return leakageColorScale.leaker3;
		    } else {
		      return "#101010"
		    }
		  } // end fill

		  function name(d) {
		    return d.parent
		        ? name(d.parent) + " > " + d.name
		        : d.name;
		  }

		  function foreign(foreign){ /* added */
		      foreign.attr("x", function(d) { return x(d.x); })
		      .attr("y", function(d) { return y(d.y); })
		      .attr("width", function(d) { return x(d.x + d.dx) - x(d.x); })
		      .attr("height", function(d) { return y(d.y + d.dy) - y(d.y); });
		    }

		  }
		  
		  $(document).ready(function(){ // document read function
		    $('#report').removeClass("disabled");
		    $('#report').removeClass("active"); // idk why the button is becoming activated

			$('#loyalists').removeClass("disabled");

		    // }); // xhr

		    // create legend
		    $('#legend')[0].innerHTML = "Percent of visits captured: ";
		    var leakageColorScale = ["#337ab7", "#63a0d4", "#9fc5e5", "#dbe9f5", "#f9e2e2", "#f4cecd", "#e7908e", "#d9534f"];
		    var leakageLabels = ['87.5% - 100%', '75% - 87.5%', '62.5% - 75%', '50% - 62.5%', '37.5% - 50%', '25% - 37.5%', '12.5% - 25%', '0 - 12.5%']
		    var colors = d3.scale.quantize()
		      .range(leakageColorScale);
		    var legend = d3.select('#legend')
		      .append('ul')
		        .attr('class', 'list-inline');

		    var keys = legend.selectAll('li.key')
		        .data(colors.range());

		    keys.enter().append('li')
		        .attr('class', 'key')
		        .style('border-top-color', String)
		        .text(function(d, i) {
		            return leakageLabels[i]
		        });

		  }); // end document ready function

		  $('.grandparent').show();

		  	phTreemap.buildTreemap(root, "#allPhysiciansChart");
		  	phTreemap.buildTreemap(loyaliststree, "#loyalistsChart");
			phTreemap.buildTreemap(splitters, "#splittersChart");
			initialized = true;

			window.addEventListener("resize", function() {
				$('#allPhysiciansChart').empty();
				$('#loyalistsChart').empty();
				$('#splittersChart').empty();
				phTreemap.buildTreemap(root, "#allPhysiciansChart");
				phTreemap.buildTreemap(loyaliststree, "#loyalistsChart");
				phTreemap.buildTreemap(splitters, "#splittersChart");
			});
		};

		if (options){
			build(options.data);
		} else {
			d3.json(endpoint, function(root) {
				build(root);
			});
		}
	}
	return this
})(jQuery)