# Lycento SDK for Rust

[![Crates.io](https://img.shields.io/crates/v/lycento-sdk.svg)](https://crates.io/crates/lycento-sdk)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
[![Docs.rs](https://docs.rs/lycento-sdk/badge.svg)](https://docs.rs/lycento-sdk)

A comprehensive Rust SDK for the Lycento licensing platform, designed for integration with Tauri desktop applications.

## Description

Lycento SDK provides a complete client library for managing software licenses in Rust applications. It handles license activation, validation, and deactivation with automatic device identification, making it ideal for desktop applications built with Tauri or other Rust frameworks.

## Installation

### From crates.io

Add this to your `Cargo.toml`:

```toml
[dependencies]
lycento-sdk = "1.0.0"
```

### From git

```toml
[dependencies]
lycento-sdk = { git = "https://github.com/lycento/sdk", branch = "main" }
```

## Quick Start

```rust
use lycento_sdk::{LycentoClient, LycentoConfig, ActivateOptions, ValidateOptions};

#[tokio::main]
async fn main() Result<(), Box<dyn std::error::Error>> {
    let config = LycentoConfig::new("https://api.lycento.com")
        .with_api_key("your-api-key")
        .with_timeout(10000);

    let client = LycentoClient::new(config)?;

    let license_key = "YOUR-LICENSE-KEY";

    let response = client
        .activate(ActivateOptions::new(license_key))
        .await?;
    println!("License activated: {:?}", response.license.status);

    let validation = client.validate_license(license_key).await?;
    println!("License valid: {}", validation.valid);

    let is_valid = client.is_valid(license_key).await;
    println!("Quick check: {}", is_valid);

    Ok(())
}
```

## Features

- **License Activation** - Activate licenses with automatic device registration
- **License Validation** - Validate license status and expiration
- **License Deactivation** - Deactivate licenses from current or specific devices
- **Device Information** - Automatic device ID generation using system identifiers
- **Full Async/Await** - Built on Tokio for async operations
- **Tauri Ready** - Designed specifically for Tauri desktop applications
- **Error Handling** - Comprehensive error types for all failure scenarios
- **Configurable** - Customizable timeouts, base URLs, and API keys

## API Reference

### LycentoClient

The main client for all license operations.

```rust
let config = LycentoConfig::new("https://api.lycento.com");
let client = LycentoClient::new(config)?;

client.activate(ActivateOptions::new("license-key")).await?;
client.validate_license("license-key").await?;
client.is_valid("license-key").await;
client.get_info("license-key").await?;
client.can_activate("license-key").await?;
client.deactivate(DeactivateOptions::new("license-key")).await?;
client.deactivate_current("license-key").await?;
```

### LycentoConfig

Configuration builder for the client.

```rust
let config = LycentoConfig::new("https://api.lycento.com")
    .with_api_key("your-api-key")
    .with_timeout(10000);
```

### ActivateOptions

Options for license activation.

```rust
let options = ActivateOptions::new("license-key")
    .with_platform(Platform::Windows)
    .with_device_name("My Device")
    .with_device_id("custom-device-id");
```

### ValidateOptions

Options for license validation.

```rust
let options = ValidateOptions::new("license-key")
    .with_device_id("custom-device-id");
```

### DeactivateOptions

Options for license deactivation.

```rust
let options = DeactivateOptions::new("license-key")
    .with_device_id("device-to-deactivate");
```

## Error Handling

The SDK provides comprehensive error types:

```rust
use lycento_sdk::{LycentoError, ActivationError, ValidationError, DeactivationError, NetworkError};

match client.validate_license(license_key).await {
    Ok(response) => println!("Valid: {}", response.valid),
    Err(LycentoError::Validation(ValidationError::Expired)) => {
        println!("License has expired");
    }
    Err(LycentoError::Validation(ValidationError::NotActivated)) => {
        println!("License not activated on this device");
    }
    Err(LycentoError::Activation(ActivationError::MaxDevicesReached)) => {
        println!("Maximum devices reached for this license");
    }
    Err(LycentoError::Network(NetworkError::Timeout)) => {
        println!("Request timed out");
    }
    Err(e) => println!("Error: {}", e),
}
```

### Error Types

| Error Type          | Description                                   |
| ------------------- | --------------------------------------------- |
| `LycentoError`      | Top-level error enum wrapping all error types |
| `ActivationError`   | Errors during license activation              |
| `ValidationError`   | Errors during license validation              |
| `DeactivationError` | Errors during license deactivation            |
| `NetworkError`      | Network and HTTP-related errors               |

## Tauri Integration

The SDK integrates seamlessly with Tauri applications. Here's an example of exposing license functionality to your frontend:

```rust
use lycento_sdk::{LycentoClient, LycentoConfig, ActivateOptions};
use tauri::State;
use std::sync::Mutex;

struct AppState {
    client: Mutex<LycentoClient>,
}

#[tauri::command]
async fn activate_license(
    state: State<'_, AppState>,
    license_key: String,
) -> Result<String, String> {
    let client = state.client.lock().unwrap();
    let result = client
        .activate(ActivateOptions::new(&license_key))
        .await
        .map_err(|e| e.to_string())?;
    Ok(result.license.status)
}

#[tauri::command]
async fn validate_license(
    state: State<'_, AppState>,
    license_key: String,
) -> Result<bool, String> {
    let client = state.client.lock().unwrap();
    let result = client
        .validate_license(&license_key)
        .await
        .map_err(|e| e.to_string())?;
    Ok(result.valid)
}

fn main() {
    let config = LycentoConfig::new("https://api.lycento.com")
        .with_api_key(std::env::var("LYCENTO_API_KEY").unwrap_or_default());

    tauri::Builder::default()
        .manage(AppState {
            client: Mutex::new(LycentoClient::new(config).unwrap()),
        })
        .invoke_handler(tauri::generate_handler![activate_license, validate_license])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
```

## Examples

See [examples/basic_usage.rs](examples/basic_usage.rs) for a complete working example.

Run the example:

```bash
cd sdks/rust
LYCENTO_BASE_URL=https://api.lycento.com LYCENTO_API_KEY=your-key cargo run --example basic_usage
```

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

```
MIT License

Copyright (c) 2025 Lycento

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
