// Erzeugt aus tokens/quelle - nicht von Hand aendern, sondern `pnpm tokens` laufen lassen.
// Dieselben Rollen wie tokens/*.css, fuer apps/apple. Noch nicht in Xcode eingebunden.
import SwiftUI
#if canImport(UIKit)
import UIKit
#elseif canImport(AppKit)
import AppKit
#endif

/// Farbrollen. Jede Rolle traegt hell und dunkel und entscheidet zur Laufzeit nach dem Erscheinungsbild.
public enum AlbertFarbe {
    /// Seitenhintergrund, warmes Creme
    public static let grund = AlbertFarbe.dynamisch(hell: 0xF8F2E7, dunkel: 0x14110D)
    /// Standardkarte (Termin), beige
    public static let karte = AlbertFarbe.dynamisch(hell: 0xEEE8DD, dunkel: 0x2A2620)
    /// Tagesreiter, Menüs, Badges auf Karten, Suchfeld
    public static let hell = AlbertFarbe.dynamisch(hell: 0xFBF7EE, dunkel: 0x201C17)
    /// Segment-Regler inaktiv, sekundäre Knöpfe
    public static let knopfZweit = AlbertFarbe.dynamisch(hell: 0xEDE6D8, dunkel: 0x322D26)
    /// Leiste, primäre Knöpfe, heutiger Tag, aktive Auswahl
    public static let schwarz = AlbertFarbe.dynamisch(hell: 0x171717, dunkel: 0x0B0A08)
    /// Schwarz unter dem Zeiger (Knopf, Kreis, heutiger Reiter)
    public static let schwarzZeiger = AlbertFarbe.dynamisch(hell: 0x2C2C2C, dunkel: 0x2C2C2C)
    /// Schwarz beim Drücken
    public static let schwarzDruck = AlbertFarbe.dynamisch(hell: 0x3A3A3A, dunkel: 0x3A3A3A)
    /// Fließtext, Titel
    public static let tinte = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0xF4EFE6)
    /// Zweittext, Zeiten, Beschriftungen
    public static let grau = AlbertFarbe.dynamisch(hell: 0x6E6A63, dunkel: 0xA9A297)
    /// Haarlinien 1 px, Ränder von Feldern und Kreisen
    public static let linie = AlbertFarbe.dynamisch(hell: 0xD8D0BF, dunkel: 0x3D372E)
    /// Akzent: Plus, Jetzt-Zeit, aktiver Ort, Zähler, Lupe
    public static let rosa = AlbertFarbe.dynamisch(hell: 0xF3B8DF, dunkel: 0xF3B8DF)
    /// Zustands-Pillen, Tageskreis mit Offenem
    public static let rosaHell = AlbertFarbe.dynamisch(hell: 0xF7CDE8, dunkel: 0xF7CDE8)
    /// Familie und Rituale, Alberts Vorschlag (iPhone), Zahlen
    public static let gelb = AlbertFarbe.dynamisch(hell: 0xF5D95C, dunkel: 0xF5D95C)
    /// Formen auf gelben Karten
    public static let gelbDunkel = AlbertFarbe.dynamisch(hell: 0xE4C63A, dunkel: 0xE4C63A)
    /// Bewertung: gut (HQ)
    public static let ampelGruen = AlbertFarbe.dynamisch(hell: 0xBFD9A6, dunkel: 0xBFD9A6)
    /// Bewertung: Potenzial (HQ)
    public static let ampelGelb = AlbertFarbe.dynamisch(hell: 0xF5D95C, dunkel: 0xF5D95C)
    /// Bewertung: schwach (HQ)
    public static let ampelRot = AlbertFarbe.dynamisch(hell: 0xEBA7A0, dunkel: 0xEBA7A0)
    public static let textAufAmpel = AlbertFarbe.dynamisch(hell: 0x2B2A25, dunkel: 0x2B2A25)
    /// Fahrten
    public static let blau = AlbertFarbe.dynamisch(hell: 0xBFCDF0, dunkel: 0xBFCDF0)
    /// Formen auf blauen Karten
    public static let blauDunkel = AlbertFarbe.dynamisch(hell: 0x9DB1E3, dunkel: 0x9DB1E3)
    /// nur gestrichelter Rand für „ohne Zuständigen“
    public static let offen = AlbertFarbe.dynamisch(hell: 0xB8467F, dunkel: 0xF09CC6)
    /// Zweittext auf gelben Flächen
    public static let aufGelb = AlbertFarbe.dynamisch(hell: 0x4A4530, dunkel: 0x4A4530)
    /// Text und Zeichen auf Schwarz
    public static let leistentext = AlbertFarbe.dynamisch(hell: 0xF4EFE6, dunkel: 0xF4EFE6)
    /// gedämpftes Rosa-Grau für den Sonntag
    public static let sonntag = AlbertFarbe.dynamisch(hell: 0xC9A0BD, dunkel: 0xB98CAD)
    public static let flaecheSeite = AlbertFarbe.dynamisch(hell: 0xF8F2E7, dunkel: 0x14110D)
    /// was schwebt: Menü, Reiter, Feld
    public static let flaecheErhoben = AlbertFarbe.dynamisch(hell: 0xFBF7EE, dunkel: 0x201C17)
    /// Termin
    public static let flaecheKarte = AlbertFarbe.dynamisch(hell: 0xEEE8DD, dunkel: 0x2A2620)
    /// Fahrt
    public static let flaecheKarteFahrt = AlbertFarbe.dynamisch(hell: 0xBFCDF0, dunkel: 0xBFCDF0)
    /// Familie und Ritual
    public static let flaecheKarteFamilie = AlbertFarbe.dynamisch(hell: 0xF5D95C, dunkel: 0xF5D95C)
    /// Vorschlag: gestrichelt, ohne Füllung
    public static let flaecheKarteVorschlag: Color = .clear
    public static let flaecheLeiste = AlbertFarbe.dynamisch(hell: 0x171717, dunkel: 0x0B0A08)
    /// dämpft, was dahinter liegt
    public static let flaecheSchleier = AlbertFarbe.dynamisch(hell: 0x1A1A1A, hellDeckkraft: 0.32, dunkel: 0x000000, dunkelDeckkraft: 0.56)
    /// Ort in der Leiste unter dem Zeiger
    public static let leisteOrtZeiger = AlbertFarbe.dynamisch(hell: 0xF4EFE6, hellDeckkraft: 0.08, dunkel: 0xF4EFE6, dunkelDeckkraft: 0.08)
    /// aktiver Ort in der Leiste unter dem Zeiger
    public static let leisteOrtAktivZeiger = AlbertFarbe.dynamisch(hell: 0xF4EFE6, hellDeckkraft: 0.14, dunkel: 0xF4EFE6, dunkelDeckkraft: 0.14)
    public static let textKoerper = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0xF4EFE6)
    public static let textTitel = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0xF4EFE6)
    public static let textZweit = AlbertFarbe.dynamisch(hell: 0x6E6A63, dunkel: 0xA9A297)
    public static let textAufLeiste = AlbertFarbe.dynamisch(hell: 0xF4EFE6, dunkel: 0xF4EFE6)
    public static let textAufLeisteZweit = AlbertFarbe.dynamisch(hell: 0x9A948B, dunkel: 0x8C857A)
    public static let textAufGelb = AlbertFarbe.dynamisch(hell: 0x4A4530, dunkel: 0x4A4530)
    public static let textAufBlau = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0x1A1A1A)
    /// Zweittext auf blauen Flächen (Fahrt)
    public static let textAufBlauZweit = AlbertFarbe.dynamisch(hell: 0x4A4F63, dunkel: 0x4A4F63)
    public static let textAufRosa = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0x1A1A1A)
    /// gerechnet, keine Deckkraft
    public static let textInaktiv = AlbertFarbe.dynamisch(hell: 0xA29B8F, dunkel: 0x7A7469)
    public static let linieHaar = AlbertFarbe.dynamisch(hell: 0xD8D0BF, dunkel: 0x3D372E)
    /// Kontur 1,5 px statt 1 px
    public static let linieStark = AlbertFarbe.dynamisch(hell: 0xC2B8A2, dunkel: 0x524A3D)
    /// gerechnet, keine Deckkraft
    public static let linieInaktiv = AlbertFarbe.dynamisch(hell: 0xE4DDCE, dunkel: 0x2B2620)
    /// gestrichelte Jetzt-Achse
    public static let linieJetzt = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0xF4EFE6)
    /// gestrichelt grau: Vorschlag von Albert
    public static let randVorschlag = AlbertFarbe.dynamisch(hell: 0x6E6A63, dunkel: 0xA9A297)
    /// gestrichelt: ohne Zuständigen
    public static let randOffen = AlbertFarbe.dynamisch(hell: 0xB8467F, dunkel: 0xF09CC6)
    /// :focus-visible Ring
    public static let randFokus = AlbertFarbe.dynamisch(hell: 0xB8467F, dunkel: 0xF09CC6)
    /// Akzent und „jetzt“ – nie Fehler
    public static let akzent = AlbertFarbe.dynamisch(hell: 0xF3B8DF, dunkel: 0xF3B8DF)
    public static let akzentHell = AlbertFarbe.dynamisch(hell: 0xF7CDE8, dunkel: 0xF7CDE8)
    public static let akzentTief = AlbertFarbe.dynamisch(hell: 0xB8467F, dunkel: 0xF09CC6)
    public static let bedeutungFahrt = AlbertFarbe.dynamisch(hell: 0xBFCDF0, dunkel: 0xBFCDF0)
    public static let bedeutungFahrtTief = AlbertFarbe.dynamisch(hell: 0x9DB1E3, dunkel: 0x9DB1E3)
    public static let bedeutungFamilie = AlbertFarbe.dynamisch(hell: 0xF5D95C, dunkel: 0xF5D95C)
    public static let bedeutungFamilieTief = AlbertFarbe.dynamisch(hell: 0xE4C63A, dunkel: 0xE4C63A)
    public static let bedeutungTermin = AlbertFarbe.dynamisch(hell: 0xEEE8DD, dunkel: 0x2A2620)
    public static let knopfPrimaerFlaeche = AlbertFarbe.dynamisch(hell: 0x171717, dunkel: 0xF4EFE6)
    /// Druck macht die Fläche nicht dunkler, sondern die Schrift ruhiger
    public static let knopfPrimaerFlaecheZeiger = AlbertFarbe.dynamisch(hell: 0x2C2C2C, dunkel: 0xE2DACD)
    public static let knopfPrimaerFlaecheDruck = AlbertFarbe.dynamisch(hell: 0x3A3A3A, dunkel: 0xCFC6B7)
    public static let knopfPrimaerText = AlbertFarbe.dynamisch(hell: 0xF4EFE6, dunkel: 0x171717)
    public static let knopfZweitFlaeche = AlbertFarbe.dynamisch(hell: 0xEDE6D8, dunkel: 0x322D26)
    public static let knopfZweitText = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0xF4EFE6)
    public static let knopfInaktivFlaeche = AlbertFarbe.dynamisch(hell: 0xE9E2D4, dunkel: 0x2B2620)
    public static let knopfInaktivText = AlbertFarbe.dynamisch(hell: 0xA29B8F, dunkel: 0x7A7469)
    /// Anna - Mint
    public static let person1 = AlbertFarbe.dynamisch(hell: 0xD5F5C2, dunkel: 0xD5F5C2)
    /// Tobias - Türkis
    public static let person2 = AlbertFarbe.dynamisch(hell: 0xA8E5E5, dunkel: 0xA8E5E5)
    /// Felix - Flieder
    public static let person3 = AlbertFarbe.dynamisch(hell: 0xF6D0FF, dunkel: 0xF6D0FF)
    /// Lena - Pfirsich
    public static let person4 = AlbertFarbe.dynamisch(hell: 0xFFD6A5, dunkel: 0xFFD6A5)
    /// Sofia - Himmel
    public static let person5 = AlbertFarbe.dynamisch(hell: 0xAEBAFF, dunkel: 0xAEBAFF)
    /// frei
    public static let person6 = AlbertFarbe.dynamisch(hell: 0xC7EFD0, dunkel: 0xC7EFD0)
    /// frei
    public static let person7 = AlbertFarbe.dynamisch(hell: 0xFFC9C9, dunkel: 0xFFC9C9)
    /// frei
    public static let person8 = AlbertFarbe.dynamisch(hell: 0xE3DCA8, dunkel: 0xE3DCA8)
    public static let personText = AlbertFarbe.dynamisch(hell: 0x1A1A1A, dunkel: 0x1A1A1A)
    public static let personLinie1 = AlbertFarbe.dynamisch(hell: 0x8FCF6E, dunkel: 0xA6DE87)
    public static let personLinie2 = AlbertFarbe.dynamisch(hell: 0x62BFBF, dunkel: 0x7FD6D6)
    public static let personLinie3 = AlbertFarbe.dynamisch(hell: 0xD28FE8, dunkel: 0xE4A8F5)
    public static let personLinie4 = AlbertFarbe.dynamisch(hell: 0xE0A55F, dunkel: 0xF0BE7C)
    public static let personLinie5 = AlbertFarbe.dynamisch(hell: 0x7B8BE0, dunkel: 0x9AA8F0)
    public static let personLinie6 = AlbertFarbe.dynamisch(hell: 0x7FC993, dunkel: 0x98DBAA)
    public static let personLinie7 = AlbertFarbe.dynamisch(hell: 0xE08F8F, dunkel: 0xF0A8A8)
    public static let personLinie8 = AlbertFarbe.dynamisch(hell: 0xB7AE6A, dunkel: 0xCFC57F)

    static func dynamisch(hell: UInt32, hellDeckkraft: Double = 1, dunkel: UInt32, dunkelDeckkraft: Double = 1) -> Color {
        #if canImport(UIKit)
        return Color(uiColor: UIColor { spur in
            spur.userInterfaceStyle == .dark ? UIColor(hex: dunkel, deckkraft: dunkelDeckkraft) : UIColor(hex: hell, deckkraft: hellDeckkraft)
        })
        #elseif canImport(AppKit)
        return Color(nsColor: NSColor(name: nil) { bild in
            bild.bestMatch(from: [.aqua, .darkAqua]) == .darkAqua ? NSColor(hex: dunkel, deckkraft: dunkelDeckkraft) : NSColor(hex: hell, deckkraft: hellDeckkraft)
        })
        #endif
    }
}

/// Raum: 8-px-Raster, Abstaende, Zielflaechen (28 Zeiger, 44 Finger, 56 Kind), Leisten.
public enum AlbertRaum {
    public static let raumHalb: CGFloat = 4
    public static let raum1: CGFloat = 8
    public static let raum2: CGFloat = 16
    public static let raum3: CGFloat = 24
    public static let raum4: CGFloat = 32
    public static let raum5: CGFloat = 40
    public static let raum6: CGFloat = 48
    public static let raum8: CGFloat = 64
    public static let karteInnen: CGFloat = 12
    public static let karteAbstand: CGFloat = 8
    public static let flaecheRandMac: CGFloat = 32
    public static let flaecheRandPhone: CGFloat = 20
    public static let zielZeiger: CGFloat = 28
    public static let zielFinger: CGFloat = 44
    public static let zielKind: CGFloat = 56
    public static let leisteMac: CGFloat = 220
    public static let leisteMacEng: CGFloat = 72
    public static let leistePhoneHoehe: CGFloat = 64
}

/// Schrift: Familien, Gewichte, Grade, Laufweite, Zeilen.
public enum AlbertSchrift {
    public static let schriftTitel = "Bricolage Grotesque"
    public static let schriftText = "Inter"
    public static let schriftMono = "Roboto Mono"
    public static let schriftHand = "Reenie Beanie"
    public static let gewichtTitel: Font.Weight = .heavy
    public static let gewichtText: Font.Weight = .regular
    public static let gewichtTextHalb: Font.Weight = .medium
    public static let gewichtTextFest: Font.Weight = .semibold
    /// „Guten Morgen, Anna.“ auf dem Mac
    public static let gradAnredeMac: CGFloat = 40
    /// dieselbe Zeile auf dem iPhone
    public static let gradAnredePhone: CGFloat = 30
    /// Zahl-Kachel: 8,7 h
    public static let gradZahlGross: CGFloat = 34
    /// Logo in der Leiste
    public static let gradBlockTitel: CGFloat = 22
    public static let gradAbschnitt: CGFloat = 17
    /// Kartentitel
    public static let gradKartenTitel: CGFloat = 14.5
    public static let gradText: CGFloat = 14
    /// Zweitzeile, Zeiten
    public static let gradZweit: CGFloat = 12
    public static let gradKlein: CGFloat = 11
    /// Wochentag im Tagesreiter
    public static let gradKapitaelchen: CGFloat = 10
    /// eng, wie in den Screensets
    /// Anteil der Schriftgroesse (em)
    public static let laufweiteTitel: Double = -0.03
    /// Anteil der Schriftgroesse (em)
    public static let laufweiteText: Double = 0
    /// Anteil der Schriftgroesse (em)
    public static let laufweiteKapitaelchen: Double = 0.08
    public static let zeileTitel: Double = 1.02
    public static let zeileKartenTitel: Double = 1.2
    public static let zeileText: Double = 1.45
    /// Zahlen und Zeiten: tabellarische Ziffern
    public static func ziffernTabellarisch(_ schrift: Font) -> Font { schrift.monospacedDigit() }
}

/// Form: Radien, Striche, Kippung, Fokus. Keine Schatten.
public enum AlbertForm {
    /// Karten und Menüs
    public static let radiusKarte: CGFloat = 16
    /// Tagesreiter, kleine Karten
    public static let radiusKlein: CGFloat = 12
    /// iPhone-Leiste
    public static let radiusLeiste: CGFloat = 24
    /// Mac-Block
    public static let radiusBlock: CGFloat = 22
    /// Pillen, Kreise, Knöpfe
    public static let radiusPille: CGFloat = 999
    public static let strichHaar: CGFloat = 1
    /// Kontur wird stark, statt Schatten
    public static let strichStark: CGFloat = 1.5
    public static let strichGestrichelt: CGFloat = 1.5
    public static let musterGestrichelt: [CGFloat] = [5, 4]
    /// was liegt, ist leicht gekippt
    public static let kippungZettel: Angle = .degrees(0.3)
    /// was schwebt, steht gerade
    public static let kippungNull: Angle = .degrees(0)
    /// Keine Schatten - nicht verhandelbar. Tiefe kommt aus Schleier, Kontur und Kippung.
    public static let schatten: CGFloat = 0
    public static let fokusRing: CGFloat = 2
    public static let fokusAbstand: CGFloat = 2
}

/// Bewegung: kurz, ruhig, ohne Federn. Bei reduzierter Bewegung stehen alle Dauern auf null.
public enum AlbertBewegung {
    public static let dauerKurz: TimeInterval = 0.12
    public static let dauerMittel: TimeInterval = 0.2
    public static let dauerAtem: TimeInterval = 0.3
    public static func verlaufRuhig(_ dauer: TimeInterval) -> Animation { .timingCurve(0.2, 0, 0.2, 1, duration: dauer) }
    public static func verlaufAtem(_ dauer: TimeInterval) -> Animation { .timingCurve(0.4, 0, 0.6, 1, duration: dauer) }
}

#if canImport(UIKit)
private extension UIColor {
    convenience init(hex: UInt32, deckkraft: Double) {
        self.init(red: CGFloat((hex >> 16) & 0xFF) / 255, green: CGFloat((hex >> 8) & 0xFF) / 255, blue: CGFloat(hex & 0xFF) / 255, alpha: deckkraft)
    }
}
#elseif canImport(AppKit)
private extension NSColor {
    convenience init(hex: UInt32, deckkraft: Double) {
        self.init(srgbRed: CGFloat((hex >> 16) & 0xFF) / 255, green: CGFloat((hex >> 8) & 0xFF) / 255, blue: CGFloat(hex & 0xFF) / 255, alpha: deckkraft)
    }
}
#endif
