html`
<div style="position: fixed; top: 1%; right: 1%;">
${viewof stateSelection}
</div>
<div style="display: inline; float: left; width: 75vw;">
<span style="font-weight: 700; font-size: 18px;">Per capita fines and fees<br>collected by local governments in 2020</span>
</div>

${chart1}
`
chart1.drawData(stateSelection[0]);
chart1 = {
  let height = 350;
  let margin = {top: 20, right: 20, bottom: 20, left: 50};
  let innerHeight = height - margin.top - margin.bottom;
  let innerWidth = width - margin.left - margin.right;

  let selectType = "per_capita";
  let chartName = "per_capita";

  let baseFilter = dataPerCapita.filter(d => d.state == "United States");
  let baseExtDates = d3.extent(baseFilter, d => d.date);
//   let baseExtData = d3.extent(baseFilter, d => d["value"]);


  const svg = d3.create("svg")
    .attr("viewBox", [0, 0, width, height])
    .attr("id", chartName)
    .attr("font-family", "'Open Sans', sans-serif");

  const group = svg.append("g")
    .attr("transform", `translate(${margin.left}, ${margin.top})`);

  const x = d3.scaleTime()
    .domain(baseExtDates)
    .range([0, innerWidth]);

  const y = d3.scaleLinear()
    .domain([0, 75])
    .range([innerHeight, 0]);

  const xAxis = d3.axisBottom(x);

  const yAxis = d3.axisLeft(y);

  // X-Axis
  group.append("g")
    .attr("class", "x-axis")
    .attr("transform", `translate(0, ${innerHeight})`)
    .call(xAxis)
    .call(d3.axisBottom(x)
      .tickFormat(d3.timeFormat("%Y"))
      .tickSize(5)
      .ticks(5)
    )
    .call(g => g.select(".domain").remove())
    .style('color', 'rgb(129, 129, 129)')
    .style('font-size', '14px')
    .style('font-weight', 500)
    .style('font-family', "'Open Sans', sans-serif")
    .attr("stroke-opacity", 0.5);

  // Y-Axis
  group.append("g")
    .attr("class", "y-axis")
    .call(yAxis)
    .call(d3.axisLeft(y)
      .tickFormat(d3.format("$,.0f"))
      .ticks(7)
    )
    .call(g => g.select(".domain").remove())
    .call(g => g.selectAll(".tick line").clone()
      .attr("x2", innerWidth + 50))
    .call(g => g.selectAll(".tick text")
      .style("font-size", "14px")
      .style("font-weight", 500)
      .attr("fill", "rgb(129, 129, 129)")
      .attr("transform", "translate(0, -7)"))
    .call(g => g.selectAll(".tick line")
      .attr("transform", "translate(-20, 0)"))
      .attr("stroke-opacity", 0.2)
    .call(g => g.append("text")
      .attr("text-anchor", "middle")
      .style("font-size", "16px")
      .attr("fill", "currentColor"))
    .style('font-family', "'Open Sans', sans-serif");

  // Area
  let lineGroup = group.append("g")
    .attr("class", "line-group");

  let area = d3.area()
    .defined(d => !isNaN(d[selectType]))
    .curve(d3.curveCardinal.tension(0.8))
    .x(d => x(d.date))
    .y0(y(0))
    .y1(d => y(d[selectType]));

  let areaPath = lineGroup
    .append("g")
    .append("path")
    .attr("stroke-width", 4);

  group.append("line")
    .attr("class", "y-highlight")
    .attr("x1", 0)
    .attr("x2", 0)
    .attr("y1", 0)
    .attr("y2", innerHeight)
    .attr("stroke", "#d3d3d3")
    .attr("stroke-width", '30px')
    .style("opacity", 0);

  svg.node().drawData = function(selectState) {

    let filtered = dataPerCapita.filter(d => selectState === d.state);
    let selectLookup = d3.group(filtered, d => d.date.toISOString());
    let selectDates = Array.from(selectLookup).map(d => d[1][0].date);

    // let extData = d3.extent(filtered, d => d["value"]);
    let extDates = d3.extent(filtered, d => d.date);
    let selectSeries = d3.groups(filtered, d => d.state);

    x.domain(extDates);
    // y.domain([0, 75]).nice();

    areaPath
      .data(selectSeries)
      .transition()
      .duration(1000)
      .attr("d", d => area(d[1]))
      .attr("class", function(d) {
      return 'ts-line ts-line-' + d[0]; //  
    })
      .attr("fill", dataDict[selectType].color);

    
  // Chart toolTip Area (defines where hover with be active)
  let tipArea = group.append("g")
    .attr("class", "tip-area");
  
  tipArea.append('svg:rect')
    .attr('width', innerWidth)
    .attr('height', innerHeight)
    .attr('opacity', 0)
    .attr('pointer-events', 'all')
    .on('mouseover', (event) => {
      console.log('mouseover');
    })
    .on('mousemove', (event) => {
      console.log('mousemove');
    
      // Get the date on the y axis for the mouse position
      let invert = x.invert(d3.pointer(event)[0])
      let bisect = d3.bisector(function(d) { return d; }).center;
      let hoverDate = (selectDates[bisect(selectDates, invert)]);
      console.log(hoverDate);
    
      // 1) Lookup/Get values by date 2) Filter by selection group 3) Sort by top values
      let lookup = selectLookup.get(hoverDate.toISOString());

      // Display and position vertical line
      d3.select("#" + chartName + " .y-highlight")
         .attr('x1',x(hoverDate))
         .attr('x2',x(hoverDate))
         .style('opacity', 0.4);
         
  
      // Custom toolTip Content
      let tipContent = `<hr style='margin:2px; padding:0; border-top: 3px solid #333;'>`;

      lookup.map( d => {
           tipContent += `
           <b>Per Capita: ${format.per_capita(d["per_capita"])}</b><br>
           Total: ${format.raw(d["raw"] * 1e3)}`
        })
    
      
      chartTip.style("left", () => {
         if ((innerWidth - d3.pointer(event)[0]) < 199) {
              return event.pageX - (200) + "px";
            } else {
              return event.pageX + 20 + "px";
            }             
         })
        .style("top", event.pageY + 5 + "px")
        .style("display", "inline-block")
        .html(`<strong>${format.date1(hoverDate)}</strong>${tipContent}`); // toolTip Content
     })
    .on('mouseout', (event) => {
        console.log('mouseout');
        chartTip.style("display", "none"); // Hide toolTip
        d3.select("#" + chartName + " .y-highlight").style('opacity', 0); // Hide y-highlight line
        d3.selectAll("#" + chartName + " .y-highlight-point").remove(); // Remove y-highlight points 
     });
     
  };

   return svg.node();

}
chartTip = d3.select("body").append("div").attr("class", "toolTip chartTip");


format = ({
  date1: d3.timeFormat("%Y"),
  per_capita: d3.format("$,.2f"),
  raw: d3.format("$,")
})

dataDict = ({
  "per_capita": {
    label: "Local Fines & Fees",
    color: "#2879cbbf",
    lineColor: "#2879cbbf"
}

})
tempData = FileAttachment("./data/local_revenue_v3.csv").csv().then(
  function(data) {
    data.forEach(function(d) {
      d.date = d3.timeParse("%Y")(d.year);
    });
    return data;
  }
)

// dataPerCapita = tempData;

// dataRaw = aq.from(tempData)
//   .derive({value: d => +d.value})
//   .filter(d => d.type == "raw")
//   .orderby("date")
//   .objects();

dataPerCapita = aq.from(tempData)
//   .derive({value: d => +d.value})
//   .filter(d => d.type == "per capita")
  .orderby("date")
  .objects();
viewof stateSelection = {
  const options = [
    {name: "United States", value: ["United States", null, null], selected: true},
    {name: "Alabama", value: ["Alabama", 0, "01"]},
    {name: "Alaska", value: ["Alaska", 1, "02"]},
    {name: "Arizona", value: ["Arizona", 2, "04"]},
    {name: "Arkansas", value: ["Arkansas", 3, "05"]},
    {name: "California", value: ["California", 4, "06"]},
    {name: "Colorado", value: ["Colorado", 5, "08"]},
    {name: "Connecticut", value: ["Connecticut", 6, "09"]},
    {name: "Delaware", value: ["Delaware", 7, "10"]},
    // {name: "District of Columbia", value: ["DC", 8, "11"]},
    {name: "Florida", value: ["Florida", 9, "12"]},
    {name: "Georgia", value: ["Georgia", 10, "13"]},
    {name: "Hawaii", value: ["Hawaii", 11, "15"]},
    {name: "Idaho", value: ["Idaho", 12, "16"]},
    {name: "Illinois", value: ["Illinois", 13, "17"]},
    {name: "Indiana", value: ["Indiana", 14, "18"]},
    {name: "Iowa", value: ["Iowa", 15, "19"]},
    {name: "Kansas", value: ["Kansas", 16, "20"]},
    {name: "Kentucky", value: ["Kentucky", 17, "21"]},
    {name: "Louisiana", value: ["Louisiana", 18, "22"]},
    {name: "Maine", value: ["Maine", 19, "23"]},
    {name: "Maryland", value: ["Maryland", 20, "24"]},
    {name: "Massachusetts", value: ["Massachusetts", 21, "25"]},
    {name: "Michigan", value: ["Michigan", 22, "26"]},
    {name: "Minnesota", value: ["Minnesota", 23, "27"]},
    {name: "Mississippi", value: ["Mississippi", 24, "28"]},
    {name: "Missouri", value: ["Missouri", 25, "29"]},
    {name: "Montana", value: ["Montana", 26, "30"]},
    {name: "Nebraska", value: ["Nebraska", 27, "31"]},
    {name: "Nevada", value: ["Nevada", 28, "32"]},
    {name: "New Hampshire", value: ["New Hampshire", 29, "33"]},
    {name: "New Jersey", value: ["New Jersey", 30, "34"]},
    {name: "New Mexico", value: ["New Mexico", 31, "35"]},
    {name: "New York", value: ["New York", 32, "36"]},
    {name: "North Carolina", value: ["North Carolina", 33, "37"]},
    {name: "North Dakota", value: ["North Dakota", 34, "38"]},
    {name: "Ohio", value: ["Ohio", 35, "39"]},
    {name: "Oklahoma", value: ["Oklahoma", 36, "40"]},
    {name: "Oregon", value: ["Oregon", 37, "41"]},
    {name: "Pennsylvania", value: ["Pennsylvania", 38, "42"]},
    {name: "Rhode Island", value: ["Rhode Island", 39, "44"]},
    {name: "South Carolina", value: ["South Carolina", 40, "45"]},
    {name: "South Dakota", value: ["South Dakota", 41, "46"]},
    {name: "Tennessee", value: ["Tennessee", 42, "47"]},
    {name: "Texas", value: ["Texas", 43, "48"]},
    {name: "Utah", value: ["Utah", 44, "49"]},
    {name: "Vermont", value: ["Vermont", 45, "50"]},
    {name: "Virginia", value: ["Virginia", 46, "51"]},
    {name: "Washington", value: ["Washington", 47, "53"]},
    {name: "West Virginia", value: ["West Virginia", 48, "54"]},
    {name: "Wisconsin", value: ["Wisconsin", 49, "55"]},
    {name: "Wyoming", value: ["Wyoming", 50, "56"]}
  ];
  const form = html`<form style="display: flex; align-items: center; font-size: 16px;"><select name=i>${options.map(o => Object.assign(html`<option>`, {textContent: o.name, selected: o.selected}))}`;
  form.i.onchange = () => form.dispatchEvent(new CustomEvent("input"));
  form.oninput = () => form.value = options[form.i.selectedIndex].value;
  form.oninput();
  return form;
}
aq = {
  const aq = await require(`arquero@${aq_version}`);

  // load and install any additional packages
  (await Promise.all(aq_packages.map(pkg => require(pkg))))
    .forEach(pkg => aq.addPackage(pkg));

  // Add HTML table view method to tables
  aq.addTableMethod('view', toView, { override: true });

  return aq;
};
aq_version = "5.1.0";
aq_packages = [];

op = aq.op;
toView = {
  const DEFAULT_LIMIT = 100;
  const DEFAULT_NULL = value => `<span style="color: #999;">${value}</span>`;
  const tableStyle = 'margin: 0; border-collapse: collapse; width: initial;';
  const cellStyle = 'padding: 1px 5px; white-space: nowrap; overflow-x: hidden; text-overflow: ellipsis; font-variant-numeric: tabular-nums;';

  // extend table prototype to provide an HTML table view
  return function(dt, opt = {}) {
    // permit shorthand for limit
    if (typeof opt === 'number') opt = { limit: opt };
    
    // marshal cell color options
    const color = { ...opt.color };
    if (typeof opt.color === 'function') {
      // if function, apply to all columns
      dt.columnNames().forEach(name => color[name] = opt.color);
    } else {
      // otherwise, gather per-column color options
      for (const key in color) {
        const value = color[key];
        color[key] = typeof value === 'function' ? value : () => value;
      }
    }

    // marshal CSS styles as toHTML() options
    const table = `${tableStyle}`;
    const td = (name, index, row) => {
      return `${cellStyle} max-width: ${+opt.maxCellWidth || 300}px;`
        + (color[name] ? ` background-color: ${color[name](index, row)};` : '');
    };

    opt = {
      limit: DEFAULT_LIMIT,
      null: DEFAULT_NULL,
      ...opt,
      style: { table, td, th: td }
    };

    // return container div, bind table value to support viewof operator
    const size = `max-height: ${+opt.height || 270}px`;
    const style = `${size}; overflow-x: auto; overflow-y: auto;`;
    const view = html`<div style="${style}">${dt.toHTML(opt)}</div>`;
    view.value = dt;
    return view;
  };
};
function formValue(form) {
  const object = {};
  for (const input of form.elements) {
    if (input.disabled || !input.hasAttribute("name")) continue;
    let value = input.value;
    switch (input.type) {
      case "range":
      case "number": {
        value = input.valueAsNumber;
        break;
      }
      case "date": {
        value = input.valueAsDate;
        break;
      }
      case "radio": {
        if (!input.checked) continue;
        break;
      }
      case "checkbox": {
        if (input.checked) value = true;
        else if (input.name in object) continue;
        else value = false;
        break;
      }
      case "file": {
        value = input.multiple ? input.files : input.files[0];
        break;
      }
      case "select-multiple": {
        value = Array.from(input.selectedOptions, option => option.value);
        break;
      }
    }
    object[input.name] = value;
  }
  return object;
}

function form(form) {
  const container = html`<div>${form}`;
  form.addEventListener("submit", event => event.preventDefault());
  form.addEventListener("change", () => container.dispatchEvent(new CustomEvent("input")));
  form.addEventListener("input", () => container.value = formValue(form));
  container.value = formValue(form);
  return container
}
style_sheet = html`<style>
@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700;800&display=swap');

body {
  font-family: 'Open Sans', sans-serif;
}

select {
  font-family: 'Open Sans', sans-serif;
  // border-radius: 20px;
  background-color: #fff;
}

.chip-circle {
    border-radius: 50%;
    display: inline-block;
    position: relative;
    width: 10px;
    height: 10px;
  }



label {
  margin-top: 20px;
  padding: 10px;
  padding-right:15px;
  text-align: center;
  cursor: pointer;
  background-color: #fff;
    color: #2e3745;
  font-weight: 600;
}




input[type="range"] {
    -webkit-appearance: none;
    border: none;
    margin: 18px 0;
    width: 100%;
    box-shadow: -2px -2px 8px white, 2px 2px 8px rgba(black, 0.5);
}
input[type="range"]:focus {
    outline: none;
}
input[type="range"]::-webkit-slider-runnable-track {
    border: none;
    width: 100%;
    height: 5px;
    cursor: pointer;
    background: #fff;
    border-radius: 10px;
    box-shadow: rgb(204, 219, 232) 3px 3px 6px 0px inset, rgba(255, 255, 255, 0.5) -3px -3px 6px 1px inset;
}


input[type="range"]::-webkit-slider-thumb {
    height: 15px;
    width: 15px;
    border-radius: 30px;
    box-shadow: 0px 0px 4px 1px rgba(0,0,0,0.37);
    /* border: 1px solid #333; */
    background: #fff;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -5px;
}
input[type="range"]:focus::-webkit-slider-runnable-track {
    background: #fff;
    border: none;
}
input[type="range"]::-moz-range-track {
    border: none;
    width: 100%;
    height: 5px;
    cursor: pointer;
    background: #fff;
    border-radius: 10px;
    box-shadow: rgb(204, 219, 232) 3px 3px 6px 0px inset, rgba(255, 255, 255, 0.5) -3px -3px 6px 1px inset;
}
input[type="range"]::-moz-range-thumb {
    height: 15px;
    width: 15px;
    border-radius: 30px;
    box-shadow: 0px 0px 4px 1px rgba(0,0,0,0.37);
    /* border: 1px solid #333; */
    background: #fff;
    cursor: pointer;
    -webkit-appearance: none;
    margin-top: -5px;
}
input[type="range"]::-ms-track {
    border: none;
    width: 100%;
    height: 5px;
    cursor: pointer;
    background: transparent;
    border-color: transparent;
    border-width: 16px 0;
    color: transparent;
}
input[type="range"]::-ms-fill-lower {
    background: #e0e0e0;
    border-radius: 2.6px;
}
input[type="range"]::-ms-fill-upper {
    background: #e0e0e0;
    border-radius: 2.6px;
}
input[type="range"]::-ms-thumb {
    border: none;
    height: 20px;
    width: 16px;
    border-radius: 3px;
    background: #ffffff;
    cursor: pointer;
}
input[type="range"]:focus::-ms-fill-lower {
    background: #fff;
}
input[type="range"]:focus::-ms-fill-upper {
    background: #fff;
}

#grid-3 {
  display: grid;
  grid-template-columns: auto auto auto;
  background-color: #fff;
}

#grid-4 {
  display: grid;
  grid-template-columns: auto auto auto auto;
  background-color: #fff;
}

#grid-4-full {
  display: grid;
  grid-template-columns: auto auto auto auto;
  background-color: #fff;
  border-top: 1px solid #d3d3d3;
  border-right: 1px solid #d3d3d3;
  border-bottom: 1px solid #d3d3d3;
  border-left: 1px solid #d3d3d3;
}


#grid-4-top {
  display: grid;
  grid-template-columns: auto auto auto auto;
  background-color: #fff;
  border-top: 1px solid #d3d3d3;
  border-right: 1px solid #d3d3d3;
  border-left: 1px solid #d3d3d3;
}

#grid-4-bottom {
  display: grid;
  grid-template-columns: auto auto auto auto;
  background-color: #fff;
  border-bottom: 1px solid #d3d3d3;
  border-right: 1px solid #d3d3d3;
  border-left: 1px solid #d3d3d3;
}

.grid-item {
  background-color: rgba(255, 255, 255, 0.8);
  border: 1px solid #d3d3d3;
  padding: 20px;
  font-size: 16px;
  text-align: left;
}


.toolTip {
  position: absolute;
  display: none;
  min-width: 30px;
  border-radius: 0;
  height: auto;
  background: #fff;
  border: 1px solid #d3d3d3;
  padding: 4px 8px;
  font-size: .85rem;
  text-align: left;
}

.eventTip {  max-width: 140px;}
.chartTip {  max-width: 240px;}

.tip-values {  
font-weight: bold;
color: #787878;
}
.tip-values .secondary{   
font-weight: normal;
}

.tip-table {
   font-size: 12px;
   text-align: right;
   color: #787878;
}

.tip-table td, .tip-table th {
  padding-right: 4px;
  padding-left: 4px;
}

.tip-table th {
  font-size: 10px;
  text-align: right;
  color: #AAA;
  vertical-align: bottom;
}

.tip-table .row-header {
  text-align: left;
}

.tip-table .primary {
  font-weight: bold;
}



</style>`