// nucleosides.sy -- Nucleosides, nucleotides, and base pairing as native Scyla.
//
// The building blocks of DNA and RNA. Each nucleoside is a base + sugar.
// Each nucleotide is a nucleoside + phosphate group(s). Base pairing rules
// determine the double helix structure and replication fidelity.
//
// This module bridges periodic.sy (atomic masses) and codons.sy (genetic code)
// by providing the actual molecular components of nucleic acids.
//
// Sources:
//   Saenger W. Principles of Nucleic Acid Structure. Springer, 1984.
//   Nelson DL, Cox MM. Lehninger Principles of Biochemistry, 8th ed, 2021.
//   IUPAC-IUB Joint Commission on Biochemical Nomenclature, 1970/1986.
//
// Marjorie McCubbins + Aether, April 2026
// Patent pending: 64/034,536

// ═══════════════════════════════════════════════════════
// STRUCTS
// ═══════════════════════════════════════════════════════

struct NucleoBase {
    symbol: String,
    name: String,
    base_type: String,
    nucleic_acid: String,
    formula: String,
    mass: Float,
    pairs_with: String,
    bond_type: String,
    citation: String,
}

struct Nucleoside {
    symbol: String,
    name: String,
    base: String,
    sugar: String,
    formula: String,
    mass: Float,
    nucleic_acid: String,
    citation: String,
}

struct Nucleotide {
    symbol: String,
    name: String,
    base: String,
    phosphates: Int,
    formula: String,
    mass: Float,
    nucleic_acid: String,
    role: String,
    citation: String,
}

fn base(s: String, n: String, bt: String, na: String, f: String, m: Float, pw: String, bo: String, ci: String) -> NucleoBase {
    return NucleoBase { symbol: s, name: n, base_type: bt, nucleic_acid: na, formula: f, mass: m, pairs_with: pw, bond_type: bo, citation: ci }
}

fn nside(s: String, n: String, b: String, su: String, f: String, m: Float, na: String, ci: String) -> Nucleoside {
    return Nucleoside { symbol: s, name: n, base: b, sugar: su, formula: f, mass: m, nucleic_acid: na, citation: ci }
}

fn ntide(s: String, n: String, b: String, p: Int, f: String, m: Float, na: String, r: String, ci: String) -> Nucleotide {
    return Nucleotide { symbol: s, name: n, base: b, phosphates: p, formula: f, mass: m, nucleic_acid: na, role: r, citation: ci }
}

// ═══════════════════════════════════════════════════════
// THE FIVE BASES
// ═══════════════════════════════════════════════════════

fn lookup_base(symbol: String) -> NucleoBase {
    // Purines (two-ring)
    if symbol == "A" { return base("A", "Adenine", "purine", "DNA+RNA", "C5H5N5", 135.13, "T (DNA) or U (RNA)", "2 hydrogen bonds", "Watson JD, Crick FHC. Nature 171:737-738, 1953") }
    if symbol == "G" { return base("G", "Guanine", "purine", "DNA+RNA", "C5H5N5O", 151.13, "C", "3 hydrogen bonds", "Watson JD, Crick FHC. Nature 171:737-738, 1953") }

    // Pyrimidines (one-ring)
    if symbol == "C" { return base("C", "Cytosine", "pyrimidine", "DNA+RNA", "C4H5N3O", 111.10, "G", "3 hydrogen bonds", "Watson JD, Crick FHC. Nature 171:737-738, 1953") }
    if symbol == "T" { return base("T", "Thymine", "pyrimidine", "DNA only", "C5H6N2O2", 126.11, "A", "2 hydrogen bonds", "Watson JD, Crick FHC. Nature 171:737-738, 1953") }
    if symbol == "U" { return base("U", "Uracil", "pyrimidine", "RNA only", "C4H4N2O2", 112.09, "A", "2 hydrogen bonds", "Crick FHC. J Mol Biol 19:548-555, 1966") }

    // Modified bases
    if symbol == "5mC" { return base("5mC", "5-Methylcytosine", "pyrimidine", "DNA (epigenetic)", "C5H7N3O", 125.13, "G", "3 hydrogen bonds", "Razin A, Riggs AD. Science 210:604-610, 1980") }
    if symbol == "I" { return base("I", "Inosine (Hypoxanthine)", "purine", "RNA (wobble)", "C5H4N4O", 136.11, "C or U or A (wobble)", "2 hydrogen bonds", "Crick FHC. J Mol Biol 19:548-555, 1966") }

    return base("", "Unknown", "", "", "", 0.0, "", "", "")
}

// ═══════════════════════════════════════════════════════
// NUCLEOSIDES (base + sugar, no phosphate)
// ═══════════════════════════════════════════════════════

fn lookup_nucleoside(symbol: String) -> Nucleoside {
    // DNA nucleosides (base + deoxyribose)
    if symbol == "dA" { return nside("dA", "Deoxyadenosine", "Adenine", "deoxyribose", "C10H13N5O3", 251.24, "DNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "dG" { return nside("dG", "Deoxyguanosine", "Guanine", "deoxyribose", "C10H13N5O4", 267.24, "DNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "dC" { return nside("dC", "Deoxycytidine", "Cytosine", "deoxyribose", "C9H13N3O4", 227.22, "DNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "dT" { return nside("dT", "Deoxythymidine", "Thymine", "deoxyribose", "C10H14N2O5", 242.23, "DNA", "Lehninger 8th ed, Ch 8") }

    // RNA nucleosides (base + ribose)
    if symbol == "rA" { return nside("rA", "Adenosine", "Adenine", "ribose", "C10H13N5O4", 267.24, "RNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "rG" { return nside("rG", "Guanosine", "Guanine", "ribose", "C10H13N5O5", 283.24, "RNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "rC" { return nside("rC", "Cytidine", "Cytosine", "ribose", "C9H13N3O5", 243.22, "RNA", "Lehninger 8th ed, Ch 8") }
    if symbol == "rU" { return nside("rU", "Uridine", "Uracil", "ribose", "C9H12N2O6", 244.20, "RNA", "Lehninger 8th ed, Ch 8") }

    return nside("", "Unknown", "", "", "", 0.0, "", "")
}

// ═══════════════════════════════════════════════════════
// NUCLEOTIDES (base + sugar + phosphate groups)
// ═══════════════════════════════════════════════════════
//
// The monophosphates are the building blocks of DNA/RNA.
// The triphosphates are the energy-carrying substrates
// used by polymerases during replication and transcription.

fn lookup_nucleotide(symbol: String) -> Nucleotide {
    // DNA nucleotide monophosphates (incorporated into DNA strand)
    if symbol == "dAMP" { return ntide("dAMP", "Deoxyadenosine monophosphate", "Adenine", 1, "C10H14N5O6P", 331.22, "DNA", "DNA building block", "Lehninger 8th ed") }
    if symbol == "dGMP" { return ntide("dGMP", "Deoxyguanosine monophosphate", "Guanine", 1, "C10H14N5O7P", 347.22, "DNA", "DNA building block", "Lehninger 8th ed") }
    if symbol == "dCMP" { return ntide("dCMP", "Deoxycytidine monophosphate", "Cytosine", 1, "C9H14N3O7P", 307.20, "DNA", "DNA building block", "Lehninger 8th ed") }
    if symbol == "dTMP" { return ntide("dTMP", "Deoxythymidine monophosphate", "Thymine", 1, "C10H15N2O8P", 322.21, "DNA", "DNA building block", "Lehninger 8th ed") }

    // DNA triphosphates (polymerase substrates)
    if symbol == "dATP" { return ntide("dATP", "Deoxyadenosine triphosphate", "Adenine", 3, "C10H16N5O12P3", 491.18, "DNA", "DNA polymerase substrate. Hydrolyzed to dAMP + PPi during incorporation.", "Lehninger 8th ed") }
    if symbol == "dGTP" { return ntide("dGTP", "Deoxyguanosine triphosphate", "Guanine", 3, "C10H16N5O13P3", 507.18, "DNA", "DNA polymerase substrate", "Lehninger 8th ed") }
    if symbol == "dCTP" { return ntide("dCTP", "Deoxycytidine triphosphate", "Cytosine", 3, "C9H16N3O13P3", 467.16, "DNA", "DNA polymerase substrate", "Lehninger 8th ed") }
    if symbol == "dTTP" { return ntide("dTTP", "Deoxythymidine triphosphate", "Thymine", 3, "C10H17N2O14P3", 482.17, "DNA", "DNA polymerase substrate", "Lehninger 8th ed") }

    // RNA triphosphates (RNA polymerase substrates)
    if symbol == "ATP" { return ntide("ATP", "Adenosine triphosphate", "Adenine", 3, "C10H16N5O13P3", 507.18, "RNA+energy", "Universal energy currency. RNA polymerase substrate. Hydrolysis releases 30.5 kJ/mol.", "Lehninger 8th ed") }
    if symbol == "GTP" { return ntide("GTP", "Guanosine triphosphate", "Guanine", 3, "C10H16N5O14P3", 523.18, "RNA+signaling", "RNA polymerase substrate. GTPase signaling (Ras, Rho, Ran). Translation elongation factor.", "Lehninger 8th ed") }
    if symbol == "CTP" { return ntide("CTP", "Cytidine triphosphate", "Cytosine", 3, "C9H16N3O14P3", 483.16, "RNA+lipids", "RNA polymerase substrate. Phospholipid biosynthesis (CDP-diacylglycerol).", "Lehninger 8th ed") }
    if symbol == "UTP" { return ntide("UTP", "Uridine triphosphate", "Uracil", 3, "C9H15N2O15P3", 484.14, "RNA+sugars", "RNA polymerase substrate. UDP-glucose for glycogen synthesis. UDP-glucuronate for detox.", "Lehninger 8th ed") }

    // Special nucleotides
    if symbol == "cAMP" { return ntide("cAMP", "Cyclic adenosine monophosphate", "Adenine", 1, "C10H12N5O6P", 329.21, "signaling", "Second messenger. Activates PKA. Made by adenylyl cyclase from ATP. Degraded by phosphodiesterase.", "Sutherland EW. Science 177:401-408, 1972 (Nobel lecture)") }
    if symbol == "cGMP" { return ntide("cGMP", "Cyclic guanosine monophosphate", "Guanine", 1, "C10H12N5O7P", 345.21, "signaling", "Second messenger. Activates PKG. Made by guanylyl cyclase. Sildenafil (Viagra) inhibits PDE5 that degrades cGMP.", "Lehninger 8th ed") }
    if symbol == "NAD" { return ntide("NAD+", "Nicotinamide adenine dinucleotide", "Adenine+Nicotinamide", 2, "C21H27N7O14P2", 663.43, "metabolism", "Electron carrier. NAD+/NADH redox pair. Central to glycolysis, TCA cycle, oxidative phosphorylation. 300+ enzymes use it.", "Lehninger 8th ed") }
    if symbol == "FAD" { return ntide("FAD", "Flavin adenine dinucleotide", "Adenine+Riboflavin", 2, "C27H33N9O15P2", 785.55, "metabolism", "Electron carrier. FAD/FADH2 redox pair. Succinate dehydrogenase (Complex II). Derived from riboflavin (B2).", "Lehninger 8th ed") }
    if symbol == "CoA" { return ntide("CoA", "Coenzyme A", "Adenine+Pantothenate+Cysteamine", 1, "C21H36N7O16P3S", 767.53, "metabolism", "Acyl group carrier. Acetyl-CoA enters TCA cycle. Fatty acid synthesis/oxidation. Derived from pantothenic acid (B5).", "Lehninger 8th ed") }

    return ntide("", "Unknown", "", 0, "", 0.0, "", "", "")
}

// ═══════════════════════════════════════════════════════
// BASE PAIRING RULES
// ═══════════════════════════════════════════════════════

fn base_pairs_with(b: String, nucleic_acid: String) -> String {
    if b == "A" {
        if nucleic_acid == "DNA" { return "T" }
        if nucleic_acid == "RNA" { return "U" }
    }
    if b == "T" { return "A" }
    if b == "G" { return "C" }
    if b == "C" { return "G" }
    if b == "U" { return "A" }
    return ""
}

fn hydrogen_bonds(base1: String, base2: String) -> Int {
    // G-C has 3 hydrogen bonds (stronger)
    // A-T / A-U has 2 hydrogen bonds (weaker)
    if base1 == "G" { return 3 }
    if base1 == "C" { return 3 }
    if base2 == "G" { return 3 }
    if base2 == "C" { return 3 }
    return 2
}

fn is_purine(b: String) -> Bool {
    if b == "A" { return true }
    if b == "G" { return true }
    return false
}

fn is_pyrimidine(b: String) -> Bool {
    if b == "C" { return true }
    if b == "T" { return true }
    if b == "U" { return true }
    return false
}

// ═══════════════════════════════════════════════════════
// DNA MELTING TEMPERATURE ESTIMATE
// ═══════════════════════════════════════════════════════
//
// GC content determines melting temperature because G-C pairs
// have 3 H-bonds vs 2 for A-T. More GC = higher Tm.
//
// Wallace rule (short oligonucleotides < 18 bp):
//   Tm = 2(A+T) + 4(G+C) degrees Celsius
//
// For longer sequences: Tm = 64.9 + 41 * (nG+nC-16.4) / (nA+nT+nG+nC)
// Cited: Marmur J, Doty P. J Mol Biol 5:109-118, 1962

fn tm_wallace(a_count: Int, t_count: Int, g_count: Int, c_count: Int) -> Float {
    return 2.0 * (a_count + t_count) + 4.0 * (g_count + c_count)
}

// ═══════════════════════════════════════════════════════
// QUICK ACCESS
// ═══════════════════════════════════════════════════════

fn base_count() -> Int {
    return 7
}

fn nucleoside_count() -> Int {
    return 8
}

fn nucleotide_count() -> Int {
    return 17
}

fn dna_bases() -> String {
    return "A|T|G|C"
}

fn rna_bases() -> String {
    return "A|U|G|C"
}
