#!/usr/bin/env catnip
# Parsing et manipulation YAML avec PyYAML
# YAML est le format de config standard (Kubernetes, CI/CD, etc.)

yaml = import('yaml')

# Modélisation de la configuration

struct DbConfig {
    host; port;

    display(self) => { f"{self.host}:{self.port}" }
}

struct AppConfig {
    name; version; debug; port;

    display(self) => {
        mode = if self.debug { "debug" } else { "release" }
        f"{self.name} v{self.version} ({mode}, port {self.port})"
    }
}

# Validation avec match

validate = (config) => {
    errors = list()

    if config['port'] < 1 or config['port'] > 65535 {
        errors = errors + list(f"port invalide: {config['port']}")
    }

    if config['version'] == None {
        errors = errors + list("version manquante")
    }

    if config['name'] == None or config['name'] == "" {
        errors = errors + list("nom manquant")
    }

    if len(errors) > 0 {
        f"  INVALIDE: {errors}"
    } else {
        f"  OK: config valide"
    }
}

# Parsing d'une chaîne YAML

yaml_string = """
name: mon-app
version: 1.2.3
debug: true
port: 8080
features:
  - auth
  - logging
  - cache
database:
  host: localhost
  port: 5432
"""

print("⇒ Parsing YAML")
config = yaml.safe_load(yaml_string)
print(f"  Clés: {config.keys()}")

# Construction des structs depuis le YAML

print()
print("⇒ Construction des structs")
app = AppConfig(config['name'], config['version'], config['debug'], config['port'])
db = DbConfig(config['database']['host'], config['database']['port'])
print(f"  App: {app}")
print(f"  DB:  {db}")

# Validation

print()
print("⇒ Validation")
print(validate(config))

# Features via broadcasting

print()
print("⇒ Features")
features = config['features']
features.[(f) => { print(f"  - {f}") }]

# Sérialisation YAML

print()
print("⇒ Sérialisation YAML")
output = yaml.dump(config)
print(output)

# Multi-documents YAML

multi_doc = """
---
env: development
debug: true
---
env: production
debug: false
"""

print("⇒ Multi-documents YAML")
docs = yaml.safe_load_all(multi_doc)
i = 0
for doc in docs {
    i = i + 1
    mode = match doc['debug'] {
        True  => { "debug activé" }
        False => { "debug désactivé" }
    }
    print(f"  Doc {i} - env: {doc['env']}, {mode}")
}

# Création de config avec dict()

print()
print("⇒ Création de config avec dict()")
new_config = dict(
    name="catnip-demo",
    version="0.1.0",
    port=8000,
    debug=False,
)
new_app = AppConfig(new_config['name'], new_config['version'], new_config['debug'], new_config['port'])
print(f"  {new_app}")
print(f"  YAML:\n{yaml.dump(new_config)}")