//  BlockyFroggy
//  Copyright © 2017 John Ryland.
//  All rights reserved.
#pragma once
#ifndef VOXEL_MODEL_H
#define VOXEL_MODEL_H


#include <vector>
#include <map>
#include <string>
#include <cstdint>


class VoxelTriangle
{
public:
  struct { float m_x, m_y, m_z; } m_verts[3];
  struct { float m_u, m_v; } m_uvs[3];
  uint32_t m_axis;
};


class VoxelBox // (basically like a AABB - Axis aligned bounding box)
{
public:
  float m_x, m_y, m_z, m_t;  // position
  float m_w, m_d, m_h;       // size (able to scale non-uniformly, assuming z is up)
  uint32_t m_color;          // color
};


typedef std::vector<VoxelBox>       VoxelBoxList;
typedef std::vector<VoxelTriangle>  VoxelTriangleList;


struct CachedVoxelModel
{
  bool               m_dirty;
  VoxelBoxList       m_model;
  VoxelTriangleList  m_modelTriangles;
};


class VoxelModels
{
public:
  VoxelModels();
  ~VoxelModels();
  
  void reloadDataFromFile(const char* a_fileName, bool a_onlineAsset);
  VoxelBoxList& getModel(const char* name, int xOff, int yOff, int w, int h, int d, bool direction, uint32_t* x_axis, uint32_t* z_axis);
  VoxelTriangleList& getModelTriangles(const char* name, int xOff, int yOff, int w, int h, int d, bool direction, uint32_t* x_axis, uint32_t* z_axis);

  void invalidateCache() { m_voxelModelCache.clear(); }
  uint32_t getPixel(int x, int y)            { if (size_t(y*256+x) < m_decodedData.size()) return ((uint32_t*)m_decodedData.data())[y*256+x]; return 0; }
  void editPixel(int x, int y, uint32_t col) { if (size_t(y*256+x) < m_decodedData.size())
    if ( ((uint32_t*)m_decodedData.data())[y*256+x] != col ) {
      ((uint32_t*)m_decodedData.data())[y*256+x] = col; m_dataChanged = true; } }

  bool dataUpdated() { return m_dataChanged; }
  void ackDataUpdated() { m_dataChanged = false; }
  void* y_axis() { return (void*)m_decodedData.data(); }
private:
  bool m_dataChanged = true;

  void decodeData(const unsigned char* a_pngData, size_t a_dataLen);
  std::vector<unsigned char>              m_decodedData;
  size_t                                  m_decodedDataWidth, m_decodedDataHeight;
  std::map<std::string,CachedVoxelModel>  m_voxelModelCache;
};


#endif // VOXEL_MODEL_H

