#pragma once

#include "render/core/texture_manager.h"

#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

class GlesTextureManager final : public TextureManager {
public:
  GlesTextureManager();
  ~GlesTextureManager() override;

  GlesTextureManager(const GlesTextureManager&) = delete;
  GlesTextureManager& operator=(const GlesTextureManager&) = delete;

  [[nodiscard]] TextureHandle loadFromFile(const std::string& path, int targetSize = 0, bool mipmap = false) override;
  [[nodiscard]] TextureHandle
  loadFromEncodedBytes(const std::uint8_t* data, std::size_t size, bool mipmap = false) override;
  [[nodiscard]] TextureHandle
  loadFromRgba(const std::uint8_t* data, int width, int height, bool mipmap = false) override;
  [[nodiscard]] TextureHandle loadFromRaw(
      const std::uint8_t* data, std::size_t size, int width, int height, int stride, PixmapFormat format,
      bool mipmap = false
  ) override;
  [[nodiscard]] TextureHandle loadFromPixels(
      const std::uint8_t* data, int width, int height, TextureDataFormat format,
      TextureFilter filter = TextureFilter::Linear, bool mipmap = false
  ) override;
  [[nodiscard]] TextureHandle
  createEmpty(int width, int height, TextureDataFormat format, TextureFilter filter = TextureFilter::Linear) override;
  bool replace(
      TextureHandle& handle, const std::uint8_t* data, int width, int height, TextureDataFormat format,
      TextureFilter filter = TextureFilter::Linear, bool mipmap = false
  ) override;
  bool updateSubImage(
      TextureHandle& handle, const std::uint8_t* data, int x, int y, int width, int height, TextureDataFormat format
  ) override;
  void unload(TextureHandle& handle) override;
  void cleanup() override;
  void abandonGpuResources() noexcept override;

  void probeExtensions() override;

private:
  TextureHandle decodeEncodedRaster(
      const std::uint8_t* data, std::size_t size, const std::string* debugPath = nullptr, bool mipmap = false
  );
  TextureHandle uploadPixels(
      const std::uint8_t* data, int width, int height, TextureDataFormat format,
      TextureFilter filter = TextureFilter::Linear, bool mipmap = false
  );
  TextureHandle uploadRgba(const std::uint8_t* data, int width, int height, bool mipmap = false);
  TextureHandle uploadBgra(const std::uint8_t* data, int width, int height, bool mipmap = false);

  std::vector<TextureId> m_textures;
  std::uint64_t m_generation = 0;
  bool m_hasBgraExt = false;
};
