# SPC Geo

A package for fetching and processing National Weather Service (NWS) alerts and watches with geospatial data support.

## Explanation

This package connects to the NWS API to fetch active weather alerts and watches, then processes them to provide:

- **Geospatial data**: GeoJSON FeatureCollections for mapping
- **Zone lookups**: Direct access to NWS zone data (forecast zones, fire zones, counties)
- **VTEC parsing**: Start/end times from VTEC strings
- **Multiple data sources**: Handles different zone types (fire, forecast, county) automatically

## Installation

```bash
npm install @radarwave/spc-geo
```

## Quick Start

```javascript
import { NWSClient, WatchType } from '@radarwave/spc-geo';

// Preferred usage (object form)
const client = new NWSClient({
  feedBaseUrl: 'https://api.weather.gov/alerts/active', // optional, defaults to NWS API
  zoneDataPath: '/my/custom/path' // optional, browser only
});

// Minimal (all defaults)
const client2 = new NWSClient();

// Legacy usage (discouraged):
const client3 = new NWSClient('https://api.weather.gov/alerts/active', '/my/custom/path');
const client4 = new NWSClient('https://api.weather.gov/alerts/active');

// Get all active tornado watches with GeoJSON
const tornadoWatches = await client.GetOperationalWatches(
  { type: WatchType.Tornado }, 
  ["id", "geojson", "start", "to"]
);

// Each watch has a .geojson() method that returns a FeatureCollection
const geojson = tornadoWatches[0].geojson();
console.log(geojson.features.length); // Number of affected zones
```

> **Note:** The object form is preferred to avoid parameter order issues. `zoneDataPath` is only needed in the browser if your zone data is not at `/zone_data`.

## Watch Types

The package supports all major NWS watch types:

```javascript
import { WatchType } from '@radarwave/spc-geo';

// Available types:
WatchType.Tornado           // Tornado Watches
WatchType.SevereThunderstorm // Severe Thunderstorm Watches  
WatchType.FlashFlood        // Flash Flood Watches
WatchType.Flood             // Flood Watches
WatchType.Hurricane         // Hurricane Watches
WatchType.TropicalStorm     // Tropical Storm Watches
WatchType.WinterStorm       // Winter Storm Watches
WatchType.Blizzard          // Blizzard Watches
WatchType.HighWind          // High Wind Watches
WatchType.ExcessiveHeat     // Excessive Heat Watches
WatchType.ExtremeHeat       // Extreme Heat Watches
WatchType.WindChill         // Wind Chill Watches
WatchType.FreezingRain      // Freezing Rain Watches
WatchType.FireWeather       // Fire Weather Watches
WatchType.All               // All active watches
```

## Data Includes

You can specify what data to include in the results:

```javascript
const includes = [
  "id",        // Watch ID (e.g., "FWA-0005")
  "states",    // Affected state codes
  "ugc",       // UGC codes (county/zone identifiers)
  "counties",  // County names (only from county-type zones)
  "zones",     // Full zone data with geometries
  "headline",  // Watch headline text
  "details",   // Description/Probs (Tornado/Severe only)
  "start",     // Start time (from VTEC)
  "to",        // End time (from VTEC)
  "geojson"    // GeoJSON FeatureCollection
];
```

## Examples

### Get Fire Weather Watches with Zone Data

```javascript
const fireWatches = await client.GetOperationalWatches(
  { type: WatchType.FireWeather },
  ["id", "zones", "geojson", "start", "to"]
);

fireWatches.forEach(watch => {
  console.log(`Watch ${watch.id}:`);
  console.log(`Start: ${watch.start}`);
  console.log(`End: ${watch.to}`);
  console.log(`Zones: ${watch.zones.length}`);
  
  // Get GeoJSON for mapping
  const geojson = watch.geojson();
  console.log(`Features: ${geojson.features.length}`)
});
```

### Process All Active Watches

```javascript
const allWatches = await client.GetOperationalWatches(
  { type: WatchType.All },
  ["id", "states", "counties", "zones", "geojson"]
);

allWatches.forEach(watch => {
  console.log(`\n${watch.id}:`);
  console.log(`States: ${watch.states.join(', ')}`);
  console.log(`Counties: ${watch.counties.length}`);
  console.log(`Zones: ${watch.zones.length}`);
  
  // Each zone has type, id, and full data
  watch.zones.forEach(zone => {
    console.log(`    ${zone.type}: ${zone.id}`);
  });
});
```

### Get Detailed Tornado Watch Info

```javascript
const tornadoWatches = await client.GetOperationalWatches(
  { type: WatchType.Tornado },
  ["id", "headline", "details", "geojson"]
);

if (tornadoWatches.length > 0) {
  const watch = tornadoWatches[0];
  console.log(watch.headline);
  
  // Get detailed probabilities and text
  const details = await watch.details();
  console.log(details.maxProbs); // Tornado, wind, hail probabilities
  console.log(details.text);     // Watch discussion text
}
```

## GeoJSON Output

The `.geojson()` method returns a standard GeoJSON FeatureCollection:

```javascript
const geojson = watch.geojson();

// Structure:
{
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: { /* zone geometry */ },
      properties: {
        "@id": "https://api.weather.gov/zones/forecast/ILZ058",
        "id": "ILZ058",
        "type": "forecast",
        "name": "Greene",
        "state": "IL",
        "watchid": "FWA-0005",
        // ... other zone properties
      }
    }
  ]
}
```

## Performance Notes

- Zone data is loaded once per request and cached
- County/zone data is split into files by us state or prefix to load only as much as needed.
- Missing zones are logged with warnings

## Error Handling

The package handles missing data gracefully:

```javascript
try {
  const watches = await client.GetOperationalWatches(
    { type: WatchType.Tornado },
    ["id", "geojson"]
  );
  
  if (watches.length === 0) {
    console.log("No tornado watches currently active");
  }
} catch (error) {
  console.error("Failed to fetch watches:", error.message);
}
```

## Zone Data Directory (IMPORTANT for Browser Use)

The SPC Geo package relies on a directory of zone data files (in `zone_data/`) for geospatial lookups. **How you provide this data depends on your environment:**

### Node.js
- The package will load zone data from the filesystem using the path you provide (e.g., `./node_modules/spc-geo/zone_data/`).
- No extra steps are needed if you use the default or a valid local path.

### Browser
- The browser cannot access local filesystem paths. It must fetch zone data via HTTP from your web server.
- **You must copy or symlink the `zone_data` directory to your web server's public/static directory.**
- Then, set `zoneDataPath` to the HTTP-accessible path (e.g., `/zone_data/`).

#### Example: Copying zone_data for Browser Use

If you installed `spc-geo` via npm, you can copy the data like this:

```sh
cp -r ./node_modules/spc-geo/zone_data ./public/zone_data
```

Or on Windows:
```sh
xcopy /E /I .\node_modules\spc-geo\zone_data .\public\zone_data
```

Then, in your browser code:
```js
const nwc = new NWSClient({
  zoneDataPath: '/zone_data/'
});
```

> **Note:** The path must match where your web server serves the files. If you use a different public directory, adjust accordingly.

