// Package battery provides battery information for the host and connected devices.
package battery

import (
	"errors"
	"sort"
	"strconv"
	"strings"
)

const (
	stateUnknown uint8 = iota
	stateEmpty
	stateFull
	stateCharging
	stateDischarging
	stateIdle
)

// Battery is a readable battery reported by the operating system.
type Battery struct {
	Name                  string
	Percent               uint8
	State                 uint8
	FullChargeCapacity    uint64
	HasFullChargeCapacity bool
	System                bool
}

var errNoBatteries = errors.New("no readable batteries")

// normalizeBatteries supplies stable fallback names and disambiguates duplicates.
func normalizeBatteries(batteries []Battery) []Battery {
	nameCounts := make(map[string]int, len(batteries))
	for i := range batteries {
		name := strings.TrimSpace(batteries[i].Name)
		if name == "" {
			name = "Battery " + strconv.Itoa(i+1)
		}
		nameCounts[name]++
		if nameCounts[name] > 1 {
			name += " (" + strconv.Itoa(nameCounts[name]) + ")"
		}
		batteries[i].Name = name
	}
	return batteries
}

// Primary returns the representative battery. Reported full-charge capacity wins,
// then system-scoped devices, then name for deterministic ties.
func Primary(batteries []Battery) (Battery, bool) {
	if len(batteries) == 0 {
		return Battery{}, false
	}
	ordered := append([]Battery(nil), batteries...)
	sort.SliceStable(ordered, func(i, j int) bool {
		a, b := ordered[i], ordered[j]
		if a.HasFullChargeCapacity != b.HasFullChargeCapacity {
			return a.HasFullChargeCapacity
		}
		if a.HasFullChargeCapacity && a.FullChargeCapacity != b.FullChargeCapacity {
			return a.FullChargeCapacity > b.FullChargeCapacity
		}
		if a.System != b.System {
			return a.System
		}
		return a.Name < b.Name
	})
	return ordered[0], true
}
