// Managed fixture only. This file and its stub types are never plugin inputs.
using System;
using System.Collections.Generic;
using System.Reflection;
using Bmaju.InnerMinmus.RingShadows;
using UnityEngine;
namespace UnityEngine
{
    public struct Color { public float r,g,b,a;public Color(float r,float g,float b,float a) { this.r=r;this.g=g;this.b=b;this.a=a; } }
    public struct Vector4 { public float x,y,z,w;public Vector4(float x,float y,float z,float w) { this.x=x;this.y=y;this.z=z;this.w=w; } }
    public class Shader { public string name="Scatterer-EVE/RaymarchCloud"; }
    public class Material
    {
        public Shader shader=new Shader();public bool FailNextVector;
        readonly Dictionary<string,float> floats=new Dictionary<string,float>();
        readonly Dictionary<string,Vector4> vectors=new Dictionary<string,Vector4>();
        readonly Dictionary<string,Color> colours=new Dictionary<string,Color>();
        readonly HashSet<string> keywords=new HashSet<string>();
        public float GetFloat(string n) { float v;return floats.TryGetValue(n,out v)?v:0; }
        public int GetInt(string n) { return (int)GetFloat(n); }
        public void SetFloat(string n,float v) { floats[n]=v; }
        public Vector4 GetVector(string n) { Vector4 v;return vectors.TryGetValue(n,out v)?v:new Vector4(); }
        public Vector4 GetVector(int n) { return GetVector(n.ToString()); }
        public void SetVector(string n,Vector4 v) { if(FailNextVector) { FailNextVector=false;throw new Exception("simulated native write error"); } vectors[n]=v; }
        public void SetVector(int n,Vector4 v) { SetVector(n.ToString(),v); }
        public Color GetColor(string n) { Color v;return colours.TryGetValue(n,out v)?v:new Color(); }
        public void SetColor(string n,Color v) { colours[n]=v; }
        public bool IsKeywordEnabled(string n) { return keywords.Contains(n); }
        public void EnableKeyword(string n) { keywords.Add(n); }
        public void DisableKeyword(string n) { keywords.Remove(n); }
    }
    public static class Debug { public static void Log(string s) { } public static void LogWarning(string s) { } }
}
namespace HarmonyLib
{
    public class HarmonyMethod { public MethodInfo method;public HarmonyMethod(MethodInfo m) { method=m; } }
    public class Harmony
    {
        public static int Patches,Unpatches;
        public Harmony(string id) { }
        public object Patch(MethodBase original,HarmonyMethod prefix,HarmonyMethod postfix,HarmonyMethod transpiler,HarmonyMethod finalizer)
        { Patches++;return null; }
        public void UnpatchAll(string id) { Unpatches++; }
    }
}
namespace Bmaju.InnerMinmus.RingShadows
{
    public class RingGlowController
    {
        public bool HasLight=true;
        public bool TryCloudLight(double h,out CloudLight light)
        { light=new CloudLight { Colour=new D3(0.12,0.06,0.03),Direction=new D3(0,1,0),Spread=0.4 };return HasLight; }
    }
    public static class RingShadowsAddon
    {
        public static Type TypeNamed(string n) { return typeof(RingShadowsAddon).Assembly.GetType(n); }
        public static object Read(object obj,string n)
        {
            if(obj==null) return null;Type t=obj as Type??obj.GetType();object target=obj is Type?null:obj;
            const BindingFlags f=BindingFlags.Instance|BindingFlags.Static|BindingFlags.Public|BindingFlags.NonPublic;
            var field=t.GetField(n,f);return field==null?null:field.GetValue(target);
        }
    }
}
class Profile
{
    public string Body="Kerbin";public bool Enabled=true,Eligible=true;
    public double Height=3000,Intensity=1,TintR=1,TintG=1,TintB=1;
}
class Layer { public Profile profile; }
class Saved { public Layer layer; }
class MunGlow
{
    public static MunGlow instance;
    public Dictionary<Material,Saved> saved=new Dictionary<Material,Saved>();
    public bool rendering=true,on=true,broken=false,cloudLightingEnabled=true,phaseAdapterAvailable=true;
    public object ownerCamera;public string hostName="Kerbin";public int eveDirectionId=43;
    public void Apply(Material m) { }
    public void PatchCloudMaterial(Material m,string name,Profile p,double h) { }
    public static void BeforeSolarUniforms(Material m) { }
    public static void AfterSolarUniforms(Material m) { }
    public void Restore() { }
}
class CloudBridgeTests
{
    static int passed;
    static bool Near(double a,double b) { return Math.Abs(a-b)<1e-6; }
    static void Check(bool ok,string name) { if(!ok) throw new Exception(name);passed++;Console.WriteLine("PASS "+name); }
    static Material Make()
    {
        var m=new Material();m.SetColor("_sunColor",new Color(0.01f,0.02f,0.03f,1));
        m.SetVector("_Sun_WorldSunDir",new Vector4(1,0,0,0));m.SetVector(43,new Vector4(1,0,0,0));
        m.SetVector("directPhaseFunctionProperties",new Vector4(0.95f,1,-0.8f,0.5f));
        m.SetVector("multiplePhaseFunctionProperties",new Vector4(0.8f,0.3f,-0.7f,0.2f));
        m.SetFloat("useEclipses",1);m.SetFloat("godraysSoftwareSwitch",0);m.SetFloat("lightMarchSteps",8);m.SetFloat("lightMarchDistance",10000);
        m.EnableKeyword("LIGHT_VOLUME_ON");m.EnableKeyword("DISCRETE_LIGHT_SAMPLES_OFF");return m;
    }
    static void Main()
    {
        var owner=new RingGlowController();var mg=MunGlow.instance=new MunGlow();var profile=new Profile();var m=Make();
        var bridge=RingCloudBridge.Create(owner,typeof(MunGlow));
        Check(bridge!=null&&HarmonyLib.Harmony.Patches==5,"adapter resolves and registers all five render transaction hooks");
        RingCloudBridge.AfterPatch(mg,m,profile);
        Check(Near(m.GetColor("_sunColor").r,0.13),"eligible EVE layer receives ring light when MunGlow has no moon target");
        Check(m.GetVector("_Sun_WorldSunDir").y>0.9,"cloud direction follows dominant ring illumination");
        RingCloudBridge.AfterPatch(mg,m,profile);
        Check(Near(m.GetColor("_sunColor").r,0.13),"duplicate material discovery is not double lit");
        RingCloudBridge.BeforeSolar(m);
        Check(Near(m.GetColor("_sunColor").r,0.01)&&Near(m.GetVector("directPhaseFunctionProperties").x,0.95),"solar refresh restores pre-ring colour and phase");
        m.SetColor("_sunColor",new Color(0.03f,0.04f,0.05f,1));RingCloudBridge.AfterSolar(m);
        Check(Near(m.GetColor("_sunColor").r,0.15),"ring-only layer rebinds after solar uniform refresh");
        RingCloudBridge.BeforeRestore();
        Check(Near(m.GetColor("_sunColor").r,0.03)&&Near(m.GetVector(43).x,1)&&Near(m.GetFloat("useEclipses"),1)&&Near(m.GetFloat("godraysSoftwareSwitch"),0),"render completion restores colours directions and native eclipse controls");
        Check(m.IsKeywordEnabled("LIGHT_VOLUME_ON")&&!m.IsKeywordEnabled("LIGHT_VOLUME_OFF")&&m.IsKeywordEnabled("DISCRETE_LIGHT_SAMPLES_OFF"),"render completion restores light-volume and sampling keywords");
        mg.saved[m]=new Saved { layer=new Layer { profile=profile } };
        RingCloudBridge.BeforeApply(m);m.SetColor("_sunColor",new Color(0.02f,0.01f,0.01f,1));RingCloudBridge.AfterApply(mg,m);
        RingCloudBridge.BeforeApply(m);m.SetColor("_sunColor",new Color(0.02f,0.01f,0.01f,1));RingCloudBridge.AfterApply(mg,m);
        Check(Near(m.GetColor("_sunColor").r,0.14),"repeated MunGlow Apply retains moonlight without accumulating ring light");
        RingCloudBridge.BeforeRestore();mg.saved.Clear();profile.Enabled=false;RingCloudBridge.AfterPatch(mg,m,profile);
        Check(Near(m.GetColor("_sunColor").r,0.02),"disabled layer remains unmodified");profile.Enabled=true;profile.Eligible=false;
        RingCloudBridge.AfterPatch(mg,m,profile);Check(Near(m.GetColor("_sunColor").r,0.02),"ineligible effects and precipitation are skipped");profile.Eligible=true;
        mg.cloudLightingEnabled=false;RingCloudBridge.AfterPatch(mg,m,profile);Check(Near(m.GetColor("_sunColor").r,0.02),"MunGlow cloud master switch is respected");mg.cloudLightingEnabled=true;
        owner.HasLight=false;RingCloudBridge.AfterPatch(mg,m,profile);Check(Near(m.GetColor("_sunColor").r,0.02),"no ring flux leaves clouds unchanged");owner.HasLight=true;
        m.shader.name="unrelated-shader";RingCloudBridge.AfterPatch(mg,m,profile);Check(Near(m.GetColor("_sunColor").r,0.02),"unrecognized shader is not modified");m.shader.name="Scatterer-EVE/RaymarchCloud";
        RingCloudBridge.BeforeApply(null);RingCloudBridge.AfterApply(mg,null);RingCloudBridge.AfterPatch(mg,null,profile);RingCloudBridge.BeforeSolar(null);RingCloudBridge.AfterSolar(null);
        RingCloudBridge.AfterPatch(mg,m,profile);Check(Near(m.GetColor("_sunColor").r,0.14),"null material callbacks do not disable adapter");RingCloudBridge.BeforeRestore();
        m.FailNextVector=true;RingCloudBridge.AfterPatch(mg,m,profile);
        Check(Near(m.GetColor("_sunColor").r,0.02)&&Near(m.GetVector("_Sun_WorldSunDir").x,1),"partial material write restores baseline without throwing into MunGlow");
        bridge.Dispose();bridge.Dispose();Check(HarmonyLib.Harmony.Unpatches==1,"scene disposal unpatches only this owner and is idempotent");
        bridge=RingCloudBridge.Create(owner,typeof(MunGlow));RingCloudBridge.AfterPatch(mg,m,profile);
        Check(bridge!=null&&Near(m.GetColor("_sunColor").r,0.14),"new scene can attach after previous adapter failure");bridge.Dispose();
        Check(Near(m.GetColor("_sunColor").r,0.02),"disposing active adapter restores native material");
        Console.WriteLine("TOTAL "+passed+" passed; actual bridge callbacks with managed Material/Harmony fixtures, not native detours or EVE shaders");
    }
}
