using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using SharpDX;
using SharpDX.Direct3D11;
using Framefield.Core.Rendering;
using Buffer = SharpDX.Direct3D11.Buffer;

namespace Framefield.Core.IDb276a240_66a3_4414_8d24_ef0b7ee2c99d
{
    public class Class_ZebraZPhongShader : FXSourceCodeFunction, IFXSceneSourceCode, IMaterial
    {

        #region Renderer
        public class Renderer : BaseRenderer
        {
            public override void SetupEffect(OperatorPartContext context)
            {
                base.SetupEffect(context);
                try
                {
                    SetupMaterialConstBuffer(context);
                    SetupFogSettingsConstBuffer(context);
                    SetupPointLightsConstBuffer(context);
                }
                catch (Exception e)
                {
                    Logger.Error(ParentFunc, "Error building constant buffer: {0} - Source: {1}", e.Message, e.Source);
                }
            }
            public OperatorPart.Function ParentFunc {get;set;}
        }
        #endregion

        public override void Dispose() {
            Utilities.DisposeObj(ref _renderer);
            base.Dispose();
        }

        //>>> _inputids
        private enum InputId
        {
            Code = 0,
            Scene = 1,
            ColorAR = 2,
            ColorAG = 3,
            ColorAB = 4,
            ColorAA = 5,
            ColorBR = 6,
            ColorBG = 7,
            ColorBB = 8,
            ColorBA = 9,
            WidthA = 10,
            WidthB = 11,
            Offset = 12,
            FalloffThreshold = 13
        }
        //<<< _inputids
        bool _firstEval = true;
        public override OperatorPartContext Eval(OperatorPartContext context, List<OperatorPart> inputs, int outputIdx) {
            //>>> _params
            var Code = inputs[(int)InputId.Code].Eval(context).Text;
            var Scene = inputs[(int)InputId.Scene];
            var ColorAR = inputs[(int)InputId.ColorAR].Eval(context).Value;
            var ColorAG = inputs[(int)InputId.ColorAG].Eval(context).Value;
            var ColorAB = inputs[(int)InputId.ColorAB].Eval(context).Value;
            var ColorAA = inputs[(int)InputId.ColorAA].Eval(context).Value;
            var ColorA = new Color4(ColorAR, ColorAG, ColorAB, ColorAA);
            var ColorBR = inputs[(int)InputId.ColorBR].Eval(context).Value;
            var ColorBG = inputs[(int)InputId.ColorBG].Eval(context).Value;
            var ColorBB = inputs[(int)InputId.ColorBB].Eval(context).Value;
            var ColorBA = inputs[(int)InputId.ColorBA].Eval(context).Value;
            var ColorB = new Color4(ColorBR, ColorBG, ColorBB, ColorBA);
            var WidthA = inputs[(int)InputId.WidthA].Eval(context).Value;
            var WidthB = inputs[(int)InputId.WidthB].Eval(context).Value;
            var Width = new Vector2(WidthA, WidthB);
            var Offset = inputs[(int)InputId.Offset].Eval(context).Value;
            var FalloffThreshold = inputs[(int)InputId.FalloffThreshold].Eval(context).Value;
            //<<< _params
        
            if (_firstEval) {
                for (int i = 0; i < NumCodes(); ++i)
                    Compile(i);
                _firstEval = false;
                Changed = true;
            }

            var prevEffect = context.Effect;
            var prevRenderer = context.Renderer;
            context.Effect = _effect;
            context.Renderer = _renderer;
            
            //_effect.GetVariableByName("inverseProjMatrix").AsMatrix().Set();
            
            //Logger.Info("{}", Matrix.Invert(context.CameraProjection));


            _effect.GetVariableByName("ColorA").AsVector().Set(new Vector4(ColorAR, ColorAG, ColorAB,ColorAA)); 
            _effect.GetVariableByName("ColorB").AsVector().Set(new Vector4(ColorBR, ColorBG, ColorBB,ColorBA)); 
            _effect.GetVariableByName("Width").AsVector().Set(new Vector2(WidthA, WidthB)); 
            _effect.GetVariableByName("Offset").AsScalar().Set(Offset); 
            _effect.GetVariableByName("FalloffThreshold").AsScalar().Set(FalloffThreshold); 
            var v = _effect.GetVariableByName("InverseProjectionMatrix").AsMatrix();
            v.SetMatrix(Matrix.Invert(context.CameraProjection)); 
            

            Scene.Eval(context);
            
            context.Effect = prevEffect;
            context.Renderer = prevRenderer;

            return context;
        }

        private Renderer _renderer = new Renderer();

        public Color4 Ambient { get; private set; }
        public Color4 Diffuse { get; private set; }
        public Color4 Specular { get; private set; }
        public Color4 Emission { get; private set; }
        public float Shininess { get; private set; }
    }
}


