package main

import (
	"fmt"
	"log"
	"os"
	"strconv"

	"git.1e99.eu/1e99/wolbodge/devices"
	"git.1e99.eu/1e99/wolbodge/sessions"
)

func NewStorage() (sessions.Storage, error) {
	var storageType string
	Env("WOLBODGE_STORAGE_TYPE", &storageType, "mem")

	switch storageType {
	case "mem", "memory":
		return sessions.NewMemStorage(), nil

	default:
		return nil, fmt.Errorf("unknown storage type: %s", storageType)
	}
}

func NewDevice() (devices.Device, error) {
	var deviceType string
	Env("WOLBODGE_DEVICE_TYPE", &deviceType, "test")

	switch deviceType {
	case "test":
		return devices.NewTest(false), nil

	case "libgpiod":
		var gpiochip string
		var powerButtonPin int
		var powerLEDPin int
		Env("WOLBODGE_DEVICE_GPIOCHIP", &gpiochip, "gpiochip0")
		Env("WOLBODGE_DEVICE_POWER_BUTTON_PIN", &powerButtonPin, "27")
		Env("WOLBODGE_DEVICE_POWER_LED_PIN", &powerLEDPin, "17")

		return devices.NewLibgpiod(gpiochip, powerButtonPin, powerLEDPin), nil

	default:
		return nil, fmt.Errorf("unknown device type: %s", deviceType)
	}
}

func Env(name string, out any, def string) {
	raw := os.Getenv(name)
	if raw == "" {
		raw = def
		log.Printf("No \"%s\" provided, defaulting to \"%s\".", name, def)
	}

	switch value := out.(type) {
	case *int:
		i, err := strconv.ParseInt(raw, 10, 64)
		if err != nil {
			log.Printf("\"%s\" is not a number (\"%s\").", name, raw)
			return
		}

		*value = int(i)

	case *bool:
		switch raw {
		case "true", "TRUE", "1":
			*value = true
		case "false", "FALSE", "0":
			*value = false
		}

	case *string:
		*value = raw
	}
}