# Nyx Client Python

A comprehensive Python SDK for the Nyx Astronomy API providing access to
celestial objects, ephemeris calculations, astronomical events, and satellite
tracking.

## Installation

```bash
pip install nyx-client
```

Or with poetry:

```bash
poetry add nyx-client
```

## Quick Start

### Synchronous Usage

```python
from nyx_client import NyxClient

# Initialize client
client = NyxClient(api_key="your-api-key")

# List celestial objects
objects = client.objects.list(type="nebula")
for obj in objects.data:
    print(f"{obj.name}: {obj.magnitude}")

# Search for objects
results = client.objects.search(q="Orion")
for result in results.data:
    print(f"{result.object.name} (score: {result.score})")

# Get current position of Mars
position = client.ephemeris.position(
    "mars",
    latitude=34.0522,
    longitude=-118.2437
)
print(f"Mars altitude: {position.data.horizontal.altitude}°")

# Get upcoming astronomical events
events = client.events.upcoming(limit=10)
for event in events.data:
    print(f"{event.title} - {event.start_time}")

# Get ISS passes for a location
passes = client.satellites.get_passes(
    latitude=40.7128,
    longitude=-74.006,
    satellite_id="25544"
)
for pass_ in passes.data:
    print(f"ISS pass at {pass_.max_time}, max elevation: {pass_.max_elevation}°")

# Close the client when done
client.close()
```

### Async Usage

```python
import asyncio
from nyx_client import AsyncNyxClient

async def main():
    async with AsyncNyxClient(api_key="your-api-key") as client:
        # List nebulae
        objects = await client.objects.list(type="nebula", limit=5)

        # Get Mars position
        position = await client.ephemeris.position(
            "mars",
            latitude=34.0522,
            longitude=-118.2437
        )

        # Get events
        events = await client.events.upcoming(limit=5)

        return objects, position, events

asyncio.run(main())
```

### Context Manager

```python
with NyxClient(api_key="your-api-key") as client:
    objects = client.objects.list()
# Client automatically closed
```

## Configuration

### Environment Variables

```bash
export NYX_API_KEY="your-api-key"
export NYX_BASE_URL="https://api.nyx.io"
export NYX_TIMEOUT="30"
export NYX_DEBUG="false"
```

### Programmatic Configuration

```python
from nyx_client import NyxClient, NyxConfig
from nyx_client.config import TimeoutConfig, RetryConfig

config = NyxConfig(
    api_key="your-api-key",
    base_url="https://api.nyx.io",
    timeout=TimeoutConfig(
        connect=10.0,
        read=60.0,
        write=30.0
    ),
    retry=RetryConfig(
        max_retries=3,
        initial_delay=1.0,
        max_delay=30.0
    ),
    debug=True
)

client = NyxClient(config=config)
```

## API Reference

### Objects API

```python
# List objects with filtering
objects = client.objects.list(
    type="nebula",
    catalog="messier",
    constellation="Orion",
    min_magnitude=0,
    max_magnitude=10,
    page=1,
    limit=20
)

# Search objects
results = client.objects.search(q="Andromeda", limit=10)

# Get a specific object
obj = client.objects.get("messier-31")
```

### Ephemeris API

```python
# Get ephemeris data over time
ephemeris = client.ephemeris.get(
    object_id="mars",
    latitude=34.0522,
    longitude=-118.2437,
    start_time="2024-01-01T00:00:00Z",
    end_time="2024-01-02T00:00:00Z",
    step="1h"
)

# Get current position
position = client.ephemeris.position(
    "moon",
    latitude=51.5074,
    longitude=-0.1278
)

# Get rise/set times
times = client.ephemeris.rise_set(
    "sun",
    latitude=40.7128,
    longitude=-74.006,
    date="2024-06-21"
)
```

### Events API

```python
# List events
events = client.events.list(
    start_date="2024-01-01",
    end_date="2024-12-31",
    type="lunar_eclipse",
    importance="major"
)

# Get upcoming events
upcoming = client.events.upcoming(limit=10)

# Get event types
types = client.events.types()

# Get specific event
event = client.events.get("event-123")
```

### Satellites API

```python
# List satellites
satellites = client.satellites.list(
    category="space_station",
    status="active"
)

# Get satellite categories
categories = client.satellites.categories()

# Get passes for location
passes = client.satellites.get_passes(
    latitude=40.7128,
    longitude=-74.006,
    days=7,
    min_elevation=20,
    visible_only=True
)

# Get specific satellite
satellite = client.satellites.get("25544")  # ISS

# Get passes for specific satellite
iss_passes = client.satellites.get_passes_by_id(
    "25544",
    latitude=40.7128,
    longitude=-74.006,
    days=7
)
```

## Error Handling

```python
from nyx_client import NyxClient
from nyx_client.exceptions import (
    NyxApiError,
    NyxAuthenticationError,
    NyxRateLimitError,
    NyxNotFoundError,
    NyxTimeoutError,
    NyxConnectionError,
)

client = NyxClient(api_key="your-api-key")

try:
    obj = client.objects.get("nonexistent-object")
except NyxNotFoundError as e:
    print(f"Object not found: {e.message}")
except NyxRateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
except NyxAuthenticationError as e:
    print(f"Authentication failed: {e.message}")
except NyxTimeoutError as e:
    print(f"Request timed out after {e.timeout}s")
except NyxConnectionError as e:
    print(f"Connection failed: {e.message}")
except NyxApiError as e:
    print(f"API error {e.status_code}: {e.message}")
```

## Type Hints

The client provides full type hints for all API responses:

```python
from nyx_client import NyxClient
from nyx_client.types import CelestialObject, ObjectType

client = NyxClient(api_key="your-api-key")

# Type hints work with IDE autocompletion
objects = client.objects.list(type=ObjectType.NEBULA)

for obj in objects.data:
    # IDE knows obj is CelestialObject
    print(obj.name, obj.coordinates.ra, obj.coordinates.dec)
```

## License

MIT License - see LICENSE file for details.
