#ifndef MANDELBROT_APP_H
#define MANDELBROT_APP_H

#include <windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <wrl/client.h>
#include <unordered_map>
#include <mutex>
#include <string>

using Microsoft::WRL::ComPtr;

struct ConstantBuffer {
    float xmin, xmax, ymin, ymax;
    int width, height, maxIter;
    float time;
    float padding[3];
};

struct Bookmark {
    double xmin, xmax, ymin, ymax;
    int maxIter;
    bool saved = false;
};

class MandelbrotApp {
public:
    MandelbrotApp(HINSTANCE hInstance);
    ~MandelbrotApp();
    void Run();

private:
    void CreateMainWindow();
    void InitD3D();
    void CreateComputeShader();
    void ResizeBuffers(int width, int height);
    void RenderMandelbrot();
    void UpdateTitle();

    void Zoom(double factor, int centerX, int centerY);
    void Pan(int dx, int dy);
    void ResetView();
    void AdjustIterations(int delta);
    void CycleColorScheme();
    void ToggleAnimation();

    void SaveBookmark();
    void LoadBookmark(int slot);

    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    LRESULT HandleMessage(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);

    HINSTANCE hInstance_;
    HWND hwnd_;

    ComPtr<ID3D11Device> device_;
    ComPtr<ID3D11DeviceContext> context_;
    ComPtr<IDXGISwapChain> swapChain_;
    ComPtr<ID3D11RenderTargetView> renderTargetView_;
    ComPtr<ID3D11ComputeShader> computeShader_;
    ComPtr<ID3D11VertexShader> vertexShader_;
    ComPtr<ID3D11PixelShader> pixelShader_;
    ComPtr<ID3D11Buffer> constantBuffer_;
    ComPtr<ID3D11Texture2D> outputTexture_;
    ComPtr<ID3D11UnorderedAccessView> outputUAV_;
    ComPtr<ID3D11ShaderResourceView> outputSRV_;
    ComPtr<ID3D11SamplerState> samplerState_;

    double xmin_ = -2.5, xmax_ = 1.5;
    double ymin_ = -1.5, ymax_ = 1.5;
    int maxIter_ = 256;
    int colorScheme_ = 0;
    bool animationEnabled_ = false;
    float animTime_ = 0.0f;

    int imageWidth_ = 0;
    int imageHeight_ = 0;
    int lastMouseX_ = 0;
    int lastMouseY_ = 0;
    bool dragging_ = false;
    bool rightDragging_ = false;
    std::unordered_map<WPARAM, bool> keysPressed_;
    std::mutex viewMutex_;

    LARGE_INTEGER perfFreq_;
    LARGE_INTEGER lastFrameTime_;
    Bookmark bookmarks_[10];
};

#endif