using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace skyscraper8.UI.MonoGame.Bridge;

public class BaseGame : Game
{
    protected GraphicsDeviceManager _graphics;
    protected GraphicsDevice _graphicsDevice;
    protected ImGuiRenderer _imGuiRenderer;
    protected Random _rng;
    protected SpriteBatch _spriteBatch;

    protected BaseGame()
    {
        _graphics = new GraphicsDeviceManager(this);
        
        _rng = new Random();
        ChangeResolutionMode(1280, 720, true);

        IsMouseVisible = true;
    }

    protected void ChangeResolutionMode(int width, int height, bool multisampling)
    {
        _graphics.PreferredBackBufferWidth = width;
        _graphics.PreferredBackBufferHeight = height;
        _graphics.PreferMultiSampling = multisampling;
        _windowBounds = new Rectangle(0, 0, width, height);
    }

    private Rectangle _windowBounds;
    protected Rectangle WindowBounds
    {
        get
        {
            return _windowBounds;
        }
    }

    protected override void Initialize()
    {
        _imGuiRenderer = new ImGuiRenderer(this);
        _imGuiRenderer.RebuildFontAtlas();
        _imGuiRenderables = new List<ImGuiRenderable>();
        _graphicsDevice = _graphics.GraphicsDevice;
        _spriteBatch = new SpriteBatch(GraphicsDevice);
        _gameObjects = new List<GameObject>();
        Window.AllowUserResizing = false;
        base.Initialize();
    }


    protected List<GameObject> _gameObjects;
    protected override void Update(GameTime gameTime)
    {
        Monitor.Enter(_gameObjects);
        foreach (GameObject gameObject in _gameObjects)
        {
	        gameObject.Update(gameTime, _graphicsDevice);
        }
        Monitor.Exit(_gameObjects);

        Monitor.Enter(_imGuiRenderables);
        for (int i = 0; i < _imGuiRenderables.Count; i++)
        {
            if (_imGuiRenderables.Count == 0)
                continue;
            if (_imGuiRenderables[i].WasClosed())
            {
                _imGuiRenderables[i].Dispose();
                _imGuiRenderables.RemoveAt(i);
                i = 0;
                continue;
            }
        }
        foreach (ImGuiRenderable renderable in _imGuiRenderables)
        {
            renderable.Update();
        }
        Monitor.Exit(_imGuiRenderables);
    }

    protected override void Draw(GameTime gameTime)
    {
        // Call BeforeLayout first to set things up
        _imGuiRenderer.BeforeLayout(gameTime);

        //Draw our other stuff.
        _spriteBatch.Begin();
        Monitor.Enter(_gameObjects);
        foreach (GameObject gameObject in _gameObjects)
        {
            gameObject.Draw(gameTime,_spriteBatch,WindowBounds);
        }
        Monitor.Exit(_gameObjects);
        _spriteBatch.End();
        
        // Draw our UI
        ImGuiLayout();

        // Call AfterLayout now to finish up and draw all the things
        _imGuiRenderer.AfterLayout();

        base.Draw(gameTime);
    }

    protected List<ImGuiRenderable> _imGuiRenderables;
    protected virtual void ImGuiLayout()
    {
        Monitor.Enter(_imGuiRenderables);
        foreach (ImGuiRenderable renderable in _imGuiRenderables)
        {
            renderable.Render();
        }
        Monitor.Exit(_imGuiRenderables);

        if (DebugMouse)
        {
	        Console.WriteLine("X = {0}, Y = {1}", _imGuiRenderer.LastKnownMouseX, _imGuiRenderer.LastKnownMouseY);
        }
    }

    public bool DebugMouse { get; set; }
}