using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Echo.Core.Common.Packed;
using Echo.UserInterface.Backend;
using ImGuiNET;
using SDL2;
using testdrid.SdlWrapper;

namespace SDL2Demo.Forms
{
    internal class IqWindow : IRenderable
    {
        private readonly Renderer _renderer;
        private readonly Texture _texture;
        private readonly bool imgui;
        private readonly Vector2 _imguiVector;
        private bool noDraw;
        public void ResetIqGraphic()
        {
            noDraw = true;
                iqData = new byte[256][];
                for (int i = 0; i < iqData.Length; i++)
                {
                    iqData[i] = new byte[256];
                }
            noDraw = false;
        }

        public IqWindow(Renderer renderer)
        {
            ResetIqGraphic();
            _renderer = renderer;
            _texture = Texture.Create(_renderer, SDL.SDL_TextureAccess.SDL_TEXTUREACCESS_STREAMING, 256, 256);
            _texture.SetDrawBlendMode(SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
            imgui = false;
        }

        public IqWindow(ImGuiDevice imGuiDevice)
        {
            ResetIqGraphic();
            IntPtr textureIntPtr = imGuiDevice.CreateTexture(new Int2(256, 256), true, !BitConverter.IsLittleEndian);
            _texture = Texture.FromIntPointer(textureIntPtr);
            _renderer = null;
            _imguiVector = new Vector2(256, 256);
            imgui = true;
        }

        private byte[][] iqData;
        private ulong iqErrors;

        public Point RenderOffset { get; set; }

        public void PushIqSample(byte i, byte q)
        {
                if (iqData[i][q] == byte.MaxValue)
                    return;

                iqData[i][q]++;
        }

        private void RenderInternal()
        {
            if (noDraw)
                return;
            byte b = 0;
            try
            {
                for (int y = 0; y < iqData.Length; y++)
                {
                    if (noDraw)
                        return;
                    for (int x = 0; x < iqData[y].Length; x++)
                    {
                        if (noDraw)
                            return;
                        b = iqData[y][x];
                        if (b != 0)
                            _texture.SetPixel(x, y, 255, (byte)(255 - b), 0, 0);
                        else
                            _texture.SetPixel(x, y, 0, 0, 0, 0);
                    }
                }
            }
            catch (NullReferenceException e)
            {
                iqErrors++;
            }
        }

        public void Render()
        {
            _texture.Lock();
            RenderInternal();
            _texture.Unlock();

            if (imgui)
            {
                ImGui.PushStyleVar(ImGuiStyleVar.WindowMinSize, 256);
                ImGui.Begin("IQ", ImGuiWindowFlags.NoResize);
                ImGui.Image(_texture.Pointer, _imguiVector);
                ImGui.End();
            }
            else
            {
                _renderer.Copy(_texture, RenderOffset);
            }
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        internal void PushIqSamples(sbyte[] iqBuffer)
        {
            byte i, q;
            for (int idx = 0; idx < iqBuffer.Length; idx += 2)
            {
                i = (byte)(int)(iqBuffer[idx + 0] + sbyte.MaxValue);
                q = (byte)(int)(iqBuffer[idx + 1] + sbyte.MaxValue);
                PushIqSample(i, q);
            }
        }
    }
}
