```{r create-topojson}
#| echo: false     # hides the code
#| results: "hide" # hides printed output
#| message: false  # hdides messages (e.g. from package loading)
#| warning: false  # hides warnings

library(sf)
library(magrittr)

dir.create("assets",
           recursive = TRUE,
           showWarnings = FALSE)

readr::read_csv("fsa-normal-grazing-period.csv") %>%
  dplyr::transmute(
    id = `FSA Code`,
    # state = `State Name`,
    # county = `County Name`,
    year = `Program Year`,
    type = `Pasture Type`,
    start_date = `Normal Grazing Period Start Date`,
    end_date = `Normal Grazing Period End Date`,
    start_yday = lubridate::yday(`Normal Grazing Period Start Date`),
    end_yday = lubridate::yday(`Normal Grazing Period End Date`)) %>%
  readr::write_csv(
    file.path(
      "assets",
      "fsa-normal-grazing-period-simple.csv"
    ), 
    quote = "all") 

```


```{r build-legend}
#| echo: false     # hides the code
#| results: "hide" # hides printed output
#| message: false  # hides messages (e.g. from package loading)
#| warning: false  # hides warnings

library(magrittr)
library(tidyverse)

# sf::read_sf("fsa_counties.topojson") %>%
#   dplyr::left_join(
#     readr::read_csv("fsa-normal-grazing-period-simple.csv") %>%
#       dplyr::filter(year == 2020, type == "Native Pasture")
#   ) %>%
#   mapview::mapview(zcol = "start")

## yday cyclic palette
dates <- seq(lubridate::as_date("1999-07-01"), lubridate::as_date("2000-06-30"), "1 day")
color_shift <- 250
colors <- as.character(khroma::color("romaO", reverse = TRUE)(366))
colors <- colors[c((color_shift + 1):366,1:color_shift)]

yday_pal <-
  tibble::tibble(date = dates,
                 color = colors,
                 yday = lubridate::yday(dates)) %>%
  dplyr::arrange(yday)

yday_pal$color %>%
  jsonlite::write_json("assets/colors.json", auto_unbox = TRUE)

## yday cyclic legend
yday_legend <-
  yday_pal %>%
  ggplot2::ggplot(mapping = aes(x = date,
                                y = 1,
                                fill = color)) +
  geom_col(color = NA,
           linewidth = 0) +
  coord_polar(clip = "off") +
  scale_fill_identity() +
  scale_x_date(date_breaks = "month",
               date_labels = "%b"
  ) +
  ylim(-1,1.25) +
  theme_void(base_size = 24) +
  theme(legend.position = "none",
        axis.text.x = element_text(size = 16, face = "bold"),
        axis.text.y = element_blank(),
        axis.title = element_blank(),
        panel.grid = element_blank(),
        plot.margin = margin(0.1,0.1,0.1,0.1, unit = "in")
  )

ggsave(filename = "assets/legend.png",
       plot = yday_legend,
       device = ragg::agg_png,
       height = 2.5,
       width = 2.5,
       dpi = 150)
```


```{ojs inputs}
//| content: card-toolbar

// Create interactive inputs
viewof year = Inputs.range(
d3.extent(data, d => d.year),
{
step: 1, 
label: "Year",
value: 2024
}
)

viewof type = Inputs.select(
[...new Set(data.map(d => d.type))].sort(),
{
label: "Forage Type",
value: "Native Pasture"
}
)

viewof variable = Inputs.radio(
new Map([
["Season Start", "start_yday"], 
["Season End", "end_yday"]
]),
{
label: "Color by",
value: "start_yday"
}
)
```

```{ojs read-data}
//| output: false

// Import libraries
scaleSequential = (await import("https://cdn.jsdelivr.net/npm/d3@7/+esm")).scaleSequential

// a format for dates
formatDate = d3.utcFormat("%b %d, %Y")  // e.g., "Apr 18, 2025"

// counties

//counties_file = await d3.json("https://cdn.jsdelivr.net/npm/us-atlas@3/counties-10m.json");
us = await d3.json("https://sustainable-fsa.github.io/fsa-counties-dd17/fsa-counties-dd17.topojson");
//us = await d3.json("assets/fsa-counties-dd17-albers.topojson");
counties = topojson.feature(us, us.objects.counties)

// states, but just the boundaries between them
//states_file = FileAttachment("assets/fsa_states.topojson").json()
states = topojson.mesh(us, us.objects.states, (a, b) => a !== b)

// normal grazing period data, simplified
data = FileAttachment("assets/fsa-normal-grazing-period-simple.csv").csv({typed: true})

// Load color palettes
romaO = FileAttachment("assets/colors.json").json()
color = scaleSequential()
.domain([1, 366])
.interpolator(t => romaO[Math.floor(t * (romaO.length - 1))])

```

```{ojs filter-join-data}
//| output: false

// Filter CSV data to current selections
filtered = data.filter(d => d.year === year && d.type === type)

// Create a lookup table keyed by `id`
valueById = Object.fromEntries(filtered.map(d => [String(d.id).padStart(5, "0"), d[variable]]))

// Merge values into counties.features
countiesFiltered = {
  // Build lookup from filtered CSV: id → full row
  const rowById = Object.fromEntries(
        filtered.map(d => [String(d.id).padStart(5, "0"), d])
  );

  // Rebuild counties with joined properties
  return {
    type: "FeatureCollection",
    features: counties.features.map(f => {
      const id = String(f.id);
      const row = rowById[id];

      return {
        ...f,
        properties: {
          id: f.id,
          ...f.properties,
          ...(row ?? {}),
          value: row ? row[variable] : null  // explicitly add value for coloring
        }
      };
    })
  };
}

```

```{ojs}
//| label: map
//| title: FSA Normal Grazing Periods

Plot.plot({
projection: {
    type: "albers",
    domain: counties
  },
grid: true,
color: {legend: false}, // disable built-in color legend
marks: [
Plot.geo(countiesFiltered, {
      fill: d => d.properties.value != null ? color(d.properties.value) : "#ccc"
    }),

Plot.dot(
  countiesFiltered.features.map(f => {
    const [x, y] = d3.geoCentroid(f);
    return {
      ...f.properties,
      x,
      y
    };
  }),
  {
    x: "x",
    y: "y",
    r: 3,
    fill: "transparent",
    stroke: "none",
    tip: true,
    title: d => `${d.county} County, ${d.state}
FIPS: ${String(d.id).padStart(5, "0")}
Crop Type: ${type}
Start: ${d.start_date ? formatDate(d.start_date) : "None"}
End: ${d.end_date ? formatDate(d.end_date) : "None"}`
  }
),

Plot.geo(states, {stroke: "white"}),
 Plot.image([{}], { x: -76, y: 30, 
 width: 100, 
sheight: 100,
// r = 10,
 src: () => "assets/legend.png"}),
]
})

```

<!-- ## Row -->

<!-- ```{ojs} -->
<!-- Inputs.table(filtered) -->
<!-- ``` -->