"""
MikoshiLang Extended Functions - Set 24
Environmental science, ecology, and geoscience
"""
import sympy as sp
from sympy import symbols, sqrt, exp, log, pi

def get_rules():
    """Extended set 24: Environmental and earth sciences (150 functions)"""
    t, C, x = symbols('t C x')
    
    return [
        # ===== ECOLOGY (40 functions) =====
        ('SpeciesRichness[S_]', lambda S: S),
        ('ShannonDiversityIndex[p_i_]', lambda p: -sum(pi*log(pi) for pi in p if pi > 0)),
        ('SimpsonDiversityIndex[p_i_]', lambda p: 1 - sum(pi**2 for pi in p)),
        ('PielouEvennessIndex[H_, S_]', lambda H, S: H/log(S)),
        ('BergerParkerIndex[N_max_, N_total_]', lambda Nmax, Ntot: Nmax/Ntot),
        ('BrayCurtisDistance[site1_, site2_]', lambda s1, s2: sum(abs(s1i - s2i) for s1i, s2i in zip(s1, s2))/sum(s1i + s2i for s1i, s2i in zip(s1, s2))),
        ('JaccardIndex[set1_, set2_]', lambda s1, s2: len(set(s1) & set(s2))/len(set(s1) | set(s2))),
        ('SorensenIndex[set1_, set2_]', lambda s1, s2: 2*len(set(s1) & set(s2))/(len(set(s1)) + len(set(s2)))),
        ('MorisitaIndex[n1_, n2_, N1_, N2_]', lambda n1, n2, N1, N2: 2*sum(n1i*n2i for n1i, n2i in zip(n1, n2))/(sum(n1i**2 for n1i in n1)/N1**2 + sum(n2i**2 for n2i in n2)/N2**2)/(N1*N2)),
        ('RarefactionCurve[individuals_, species_]', lambda ind, spp: spp),
        ('SpeciesAreaCurve[area_, z_, c_]', lambda A, z, c: c*A**z),
        ('MacArthurWilsonModel[immigration_, extinction_]', lambda I, E: I == E),
        ('IslandBiogeography[distance_, area_]', lambda d, A: log(A)/d),
        ('NicheBreadth[p_i_]', lambda p: 1/sum(pi**2 for pi in p)),
        ('NicheOverlap[p_i_, q_i_]', lambda p, q: sum(pi*qi for pi, qi in zip(p, q))),
        ('ResourcePartitioning[niches_]', lambda n: len(n)),
        ('CarryingCapacity[resources_, consumption_]', lambda R, cons: R/cons),
        ('LogisticGrowthEcology[r_, K_, N_]', lambda r, K, N: r*N*(1 - N/K)),
        ('ExponentialGrowthEcology[r_, N_]', lambda r, N: r*N),
        ('PopulationDoublingTimeEcology[r_]', lambda r: log(2)/r),
        ('GenerationTime[age_, l_x_, m_x_]', lambda age, lx, mx: sum(agei*lxi*mxi for agei, lxi, mxi in zip(age, lx, mx))/sum(lxi*mxi for lxi, mxi in zip(lx, mx))),
        ('NetReproductiveRate[l_x_, m_x_]', lambda lx, mx: sum(lxi*mxi for lxi, mxi in zip(lx, mx))),
        ('IntrinsicRateOfIncrease[r_]', lambda r: r),
        ('LifeTable[age_, n_x_, l_x_, d_x_, q_x_]', lambda age, nx, lx, dx, qx: list(zip(age, nx, lx, dx, qx))),
        ('SurvivalCurve[l_x_]', lambda lx: lx),
        ('Mortality Rate[d_x_, n_x_]', lambda dx, nx: dx/nx),
        ('Fecundity[offspring_, females_]', lambda off, fem: off/fem),
        ('AgeDist ribution[n_x_]', lambda nx: [nxi/sum(nx) for nxi in nx]),
        ('StableAgeDistribution[leslie_matrix_]', lambda L: sp.Symbol('eigenvector')),
        ('LeslieMatrix[survival_, fecundity_]', lambda s, f: sp.Matrix([[f[0], f[1]], [s[0], 0]])),
        ('MetapopulationModel[patches_, migration_]', lambda p, m: p),
        ('SourceSinkDynamics[birth_, death_, immigration_, emigration_]', lambda b, d, i, e: b - d + i - e),
        ('RescueEffect[extinction_prob_, colonization_]', lambda pe, col: pe*(1 - col)),
        ('TrophicLevel[position_]', lambda pos: pos),
        ('FoodChainLength[levels_]', lambda lev: len(lev)),
        ('EnergyTransferEfficiency[E_out_, E_in_]', lambda Eout, Ein: Eout/Ein*100),
        ('BiomagnificationFactor[C_predator_, C_prey_]', lambda Cpred, Cprey: Cpred/Cprey),
        ('EcologicalEfficiency[production_n1_, production_n_]', lambda Pn1, Pn: Pn1/Pn*100),
        ('NetPrimaryProductivity[GPP_, R_]', lambda GPP, R: GPP - R),
        ('GrossPrimaryProductivity[photosynthesis_]', lambda P: P),
        
        # ===== BIOGEOCHEMICAL CYCLES (30 functions) =====
        ('CarbonCycle[photosynthesis_, respiration_, decomposition_]', lambda P, R, D: P - R - D),
        ('NitrogenFixation[rate_]', lambda r: r),
        ('Nitrification[NH4_, NO3_]', lambda NH4, NO3: NH4 - NO3),
        ('Denitrification[NO3_, N2_]', lambda NO3, N2: NO3 - N2),
        ('PhosphorusCycle[weathering_, uptake_, mineralization_]', lambda w, u, m: w - u + m),
        ('SulfurCycle[volcanic_, biological_]', lambda v, b: v + b),
        ('WaterCycle[precipitation_, evaporation_, runoff_]', lambda P, E, R: P - E - R),
        ('Evapotranspiration[evaporation_, transpiration_]', lambda E, T: E + T),
        ('Infiltration[precip_, runoff_, evap_]', lambda P, R, E: P - R - E),
        ('GroundwaterRecharge[infiltration_, ET_]', lambda I, ET: I - ET),
        ('StreamFlow[precipitation_, ET_, storage_change_]', lambda P, ET, dS: P - ET - dS),
        ('SedimentYield[erosion_, deposition_]', lambda eros, dep: eros - dep),
        ('WeatheringRate[temp_, precip_, rock_type_]', lambda T, P, rock: T*P*sp.Symbol('k_rock')),
        ('SoilFormation[weathering_, transport_]', lambda w, t: w - t),
        ('DecompositionRate[litter_, k_]', lambda litter, k: litter*k),
        ('CarbonSequestration[uptake_, release_]', lambda u, r: u - r),
        ('MethaneFlux[production_, oxidation_]', lambda prod, ox: prod - ox),
        ('N2OEmissions[nitrification_, denitrification_]', lambda nit, denit: nit + denit),
        ('DOCConcentration[organic_matter_]', lambda OM: OM*sp.Symbol('solubility')),
        ('DICConcentration[CO2_, HCO3_, CO3_]', lambda CO2, HCO3, CO3: CO2 + HCO3 + CO3),
        ('AlkalinityTotal[HCO3_, CO3_, OH_, H_]', lambda HCO3, CO3, OH, H: HCO3 + 2*CO3 + OH - H),
        ('pHFromCO2[CO2_, Kh_]', lambda CO2, Kh: -log(sqrt(Kh*CO2), 10)),
        ('BufferCapacity[alkalinity_]', lambda alk: alk),
        ('CarbonateSpeciation[pH_, DIC_]', lambda pH, DIC: (sp.Symbol('CO2'), sp.Symbol('HCO3'), sp.Symbol('CO3'))),
        ('CalciteSaturation[Ca_, CO3_, Ksp_]', lambda Ca, CO3, Ksp: Ca*CO3/Ksp),
        ('AragnoiteSaturation[Ca_, CO3_, Ksp_]', lambda Ca, CO3, Ksp: Ca*CO3/Ksp),
        ('OceanAcidification[pH_past_, pH_present_]', lambda pHp, pHpr: pHp - pHpr),
        ('CO2Solubility[T_, S_]', lambda T, S: exp(-60.2409 + 93.4517*(100/T) + 23.3585*log(T/100) + S*(0.023517 - 0.023656*(T/100) + 0.0047036*(T/100)**2))),
        ('GasExchange[k_, delta_C_]', lambda k, dC: k*dC),
        ('PistonVelocity[wind_, Sc_]', lambda u, Sc: 0.31*u**2*(Sc/660)**(-0.5)),
        
        # ===== POLLUTION & TOXICOLOGY (30 functions) =====
        ('AdvectionDispersion[C_, v_, D_]', lambda C, v, D: v*sp.diff(C, sp.Symbol('x')) - D*sp.diff(C, sp.Symbol('x'), 2)),
        ('DilutionFactor[C_source_, C_ambient_]', lambda Cs, Ca: Cs/Ca),
        ('MixingZone[discharge_, velocity_, depth_]', lambda Q, v, h: Q/(v*h)),
        ('PlumеDispersion[Q_, u_, sigma_y_, sigma_z_]', lambda Q, u, sigy, sigz: Q/(2*pi*u*sigy*sigz)),
        ('GaussianPlume[x_, y_, z_, H_, u_, sigma_y_, sigma_z_]', lambda x, y, z, H, u, sigy, sigz: exp(-y**2/(2*sigy**2))*(exp(-(z - H)**2/(2*sigz**2)) + exp(-(z + H)**2/(2*sigz**2)))/(2*pi*u*sigy*sigz)),
        ('AirQualityIndex[PM25_, PM10_, O3_, NO2_, SO2_, CO_]', lambda pm25, pm10, o3, no2, so2, co: max(pm25, pm10, o3, no2, so2, co)),
        ('WaterQualityIndex[DO_, BOD_, pH_, turbidity_]', lambda DO, BOD, pH, turb: (DO + 1/BOD + pH + 1/turb)/4),
        ('BiologicalOxygenDemand[C0_, k_, t_]', lambda C0, k, t: C0*(1 - exp(-k*t))),
        ('ChemicalOxygenDemand[organic_matter_]', lambda OM: OM*sp.Symbol('oxidation_factor')),
        ('DissolvedOxygen[saturation_, deficit_]', lambda sat, def_: sat - def_),
        ('OxygenSaturation[T_, S_]', lambda T, S: 14.6 - 0.41*T - 0.008*S),  # mg/L approximation
        ('OxygenDeficit[DO_sat_, DO_actual_]', lambda DOsat, DOact: DOsat - DOact),
        ('StreeterPhelps[La_, ka_, kr_, t_]', lambda La, ka, kr, t: La*ka/(kr - ka)*(exp(-ka*t) - exp(-kr*t))),
        ('CriticalDeficit[La_, ka_, kr_]', lambda La, ka, kr: La*ka/kr*(kr/ka)**(kr/(kr - ka))),
        ('Reaeration[k2_, deficit_]', lambda k2, D: k2*D),
        ('Deoxygenation[k1_, BOD_]', lambda k1, BOD: k1*BOD),
        ('Bioaccumulation[C_water_, BCF_]', lambda Cw, BCF: Cw*BCF),
        ('BioconcentrationFactor[C_organism_, C_water_]', lambda Co, Cw: Co/Cw),
        ('Bioaccumulation Factor[C_organism_, C_water_]', lambda Co, Cw: Co/Cw),
        ('BioamplificationFactor[C_predator_, C_prey_]', lambda Cpred, Cprey: Cpred/Cprey),
        ('PersistenceIndex[half_life_]', lambda t12: log(2)/t12),
        ('DegradationRate[C0_, C_, t_]', lambda C0, C, t: -log(C/C0)/t),
        ('HalfLifePollutant[k_]', lambda k: log(2)/k),
        ('ResidenceTime[volume_, flow_]', lambda V, Q: V/Q),
        ('RetentionTime[mass_, input_rate_]', lambda M, I: M/I),
        ('LoadingRate[mass_, area_, time_]', lambda M, A, t: M/(A*t)),
        ('RemovalEfficiency[C_in_, C_out_]', lambda Cin, Cout: (Cin - Cout)/Cin*100),
        ('TreatmentEfficiency[removed_, input_]', lambda rem, inp: rem/inp*100),
        ('SludgeProductionRate[BOD_removed_, yield_]', lambda BODrem, Y: BODrem*Y),
        ('HydraulicRetentionTime[V_, Q_]', lambda V, Q: V/Q),
        
        # ===== SOIL SCIENCE (25 functions) =====
        ('BulkDensitySoil[mass_dry_, volume_total_]', lambda md, Vt: md/Vt),
        ('ParticleDensity[mass_, volume_solid_]', lambda m, Vs: m/Vs),
        ('Porosity[bulk_density_, particle_density_]', lambda rhob, rhop: 1 - rhob/rhop),
        ('VoidRatioSoil[porosity_]', lambda n: n/(1 - n)),
        ('WaterContentGravimetric[mass_water_, mass_dry_]', lambda mw, md: mw/md),
        ('WaterContentVolumetric[volume_water_, volume_total_]', lambda Vw, Vt: Vw/Vt),
        ('SaturationDegree[theta_, porosity_]', lambda theta, n: theta/n),
        ('FieldCapacity[water_content_]', lambda theta: theta),  # At -33 kPa
        ('WiltingPoint[water_content_]', lambda theta: theta),  # At -1500 kPa
        ('AvailableWaterCapacity[FC_, WP_]', lambda FC, WP: FC - WP),
        ('SoilWaterPotential[psi_]', lambda psi: psi),
        ('MatricPotential[tension_]', lambda h: -h),
        ('HydraulicConductivity[K_]', lambda K: K),
        ('InfiltrationRate[i_]', lambda i: i),
        ('HortonEquation[fc_, f0_, k_, t_]', lambda fc, f0, k, t: fc + (f0 - fc)*exp(-k*t)),
        ('GreenAmptInfiltration[K_, psi_, delta_theta_, F_]', lambda K, psi, dtheta, F: K*(1 + psi*dtheta/F)),
        ('DarcysLaw[K_, dh_dl_]', lambda K, dhdl: -K*dhdl),
        ('SoilMoistureCharacteristic[theta_, psi_]', lambda theta, psi: (theta, psi)),
        ('VanGenuchtenModel[theta_s_, theta_r_, alpha_, n_, psi_]', lambda thetas, thetar, alpha, n, psi: thetar + (thetas - thetar)/(1 + (alpha*abs(psi))**n)**(1 - 1/n)),
        ('BrooksCoreyModel[theta_s_, theta_r_, psi_b_, lambda_, psi_]', lambda thetas, thetar, psib, lam, psi: thetar + (thetas - thetar)*(psi/psib)**(-lam)),
        ('SoilpH[H_concentration_]', lambda H: -log(H, 10)),
        ('CationExchangeCapacity[cmol_kg_]', lambda CEC: CEC),
        ('BaseSaturation[exchangeable_bases_, CEC_]', lambda bases, CEC: bases/CEC*100),
        ('SodiumAdsorptionRatio[Na_, Ca_, Mg_]', lambda Na, Ca, Mg: Na/sqrt((Ca + Mg)/2)),
        ('ElectricalConductivity[salinity_]', lambda EC: EC),  # dS/m
        
        # ===== GEOPHYSICS (25 functions) =====
        ('SeismicWaveVelocity[P_wave_, S_wave_]', lambda Vp, Vs: (Vp, Vs)),
        ('PWaveVelocity[K_, mu_, rho_]', lambda K, mu, rho: sqrt((K + 4*mu/3)/rho)),
        ('SWaveVelocity[mu_, rho_]', lambda mu, rho: sqrt(mu/rho)),
        ('PoissonRatioSeismic[Vp_, Vs_]', lambda Vp, Vs: (Vp**2 - 2*Vs**2)/(2*(Vp**2 - Vs**2))),
        ('RayleighWaveVelocity[Vs_]', lambda Vs: 0.92*Vs),
        ('LoveWaveVelocity[Vs_]', lambda Vs: Vs),
        ('EarthquakeMagnitude[amplitude_, distance_]', lambda A, d: log(A, 10) + 3*log(d, 10)),
        ('RichterScale[amplitude_]', lambda A: log(A, 10)),
        ('MomentMagnitude[M0_]', lambda M0: sp.Rational(2,3)*log(M0, 10) - 10.7),
        ('SeismicMoment[mu_, A_, D_]', lambda mu, A, D: mu*A*D),
        ('EnergyRelease[magnitude_]', lambda M: 10**(1.5*M + 4.8)),
        ('FocalDepth[d_]', lambda d: d),
        ('Epicentraldistance[delta_t_, v_]', lambda dt, v: dt*v),
        ('TravelTime[distance_, velocity_]', lambda d, v: d/v),
        ('SnellsLaw[v1_, v2_, i1_]', lambda v1, v2, i1: sp.asin(v2/v1*sin(i1))),
        ('ReflectionCoefficient[Z1_, Z2_]', lambda Z1, Z2: (Z2 - Z1)/(Z2 + Z1)),
        ('TransmissionCoefficient[Z1_, Z2_]', lambda Z1, Z2: 2*Z2/(Z2 + Z1)),
        ('AcousticImpedance[rho_, v_]', lambda rho, v: rho*v),
        ('GeothermalGradient[delta_T_, delta_z_]', lambda dT, dz: dT/dz),
        ('HeatFlowDensity[k_, dT_dz_]', lambda k, dTdz: -k*dTdz),
        ('ThermalConductivity[heat_flow_, gradient_]', lambda q, grad: q/grad),
        ('GravityAnomaly[g_observed_, g_theoretical_]', lambda gobs, gth: gobs - gth),
        ('BouguerAnomaly[g_obs_, g_normal_, g_free_air_, g_bouguer_]', lambda gobs, gn, gfa, gb: gobs - gn - gfa - gb),
        ('IsostasyAiry[h_, rho_crust_, rho_mantle_]', lambda h, rhoc, rhom: h*rhoc/(rhom - rhoc)),
        ('IsostasyPratt[h1_, h2_, rho1_, rho2_]', lambda h1, h2, rho1, rho2: h1*rho1 == h2*rho2),
    ]


def register():
    """Register all extended24 rules"""
    from .extended_helper import convert_rules
    return convert_rules(get_rules())
