//
//  KRShaderReflection.h
//  Kraken Engine
//
//  Copyright 2026 Kearwood Gilbert. All rights reserved.
//  
//  Redistribution and use in source and binary forms, with or without modification, are
//  permitted provided that the following conditions are met:
//  
//  1. Redistributions of source code must retain the above copyright notice, this list of
//  conditions and the following disclaimer.
//  
//  2. Redistributions in binary form must reproduce the above copyright notice, this list
//  of conditions and the following disclaimer in the documentation and/or other materials
//  provided with the distribution.
//  
//  THIS SOFTWARE IS PROVIDED BY KEARWOOD GILBERT ''AS IS'' AND ANY EXPRESS OR IMPLIED
//  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
//  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KEARWOOD GILBERT OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
//  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
//  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
//  ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//  
//  The views and conclusions contained in the software and documentation are those of the
//  authors and should not be interpreted as representing official policies, either expressed
//  or implied, of Kearwood Gilbert.
//


#pragma once

#include <map>
#include <string>
#include "hydra.h"

class KRResourceBinding;
class KRSampler;
class KRTextureBinding;
class KRCamera;

enum class ShaderValueType : uint8_t
{
  type_null = 0,
  type_bool,
  type_int32,
  type_int64,
  type_float32,
  type_float64,
  type_vector2,
  type_vector3,
  type_vector4,
  type_matrix2,
  type_matrix2x3,
  type_matrix4,
  NUM_SHADER_VALUE_TYPES
};

enum class ShaderValue : uint8_t
{
  material_baseColor_map_texture = 0,
  material_baseColor_map_texCoord,
  material_baseColor_map_scale,
  material_baseColor_map_offset,
  material_baseColor_map_rotation,
  material_baseColor_factor,
  
  material_normal_map_texture,
  material_normal_map_texCoord,
  material_normal_map_scale,
  material_normal_map_offset,
  material_normal_map_rotation,
  material_normal_scale,
  
  material_emissive_map_texture,
  material_emissive_map_texCoord,
  material_emissive_map_scale,
  material_emissive_map_offset,
  material_emissive_map_rotation,
  material_emissive_factor,
  
  material_occlusion_map_texture,
  material_occlusion_map_texCoord,
  material_occlusion_map_scale,
  material_occlusion_map_offset,
  material_occlusion_map_rotation,
  material_occlusion_strength,
  
  material_metalicRoughness_map_texture,
  material_metalicRoughness_map_texCoord,
  material_metalicRoughness_map_scale,
  material_metalicRoughness_map_offset,
  material_metalicRoughness_map_rotation,
  material_metalic_factor,
  material_roughness_factor,
  
  material_alphaMode,
  material_alphaCutoff,
  material_doubleSided,
  material_ior,
  material_shadingModel,
  
  material_anisotropy_map_texture,
  material_anisotropy_map_texCoord,
  material_anisotropy_map_scale,
  material_anisotropy_map_offset,
  material_anisotropy_map_rotation,
  material_anisotropy_strength,
  material_anisotropy_rotation,
  
  material_clearcoat_map_texture,
  material_clearcoat_map_texCoord,
  material_clearcoat_map_scale,
  material_clearcoat_map_offset,
  material_clearcoat_map_rotation,
  material_clearcoat_factor,
  
  material_clearcoatRoughness_map_texture,
  material_clearcoatRoughness_map_texCoord,
  material_clearcoatRoughness_map_scale,
  material_clearcoatRoughness_map_offset,
  material_clearcoatRoughness_map_rotation,
  material_clearcoatRoughness_factor,
  
  material_clearcoatNormal_map_texture,
  material_clearcoatNormal_map_texCoord,
  material_clearcoatNormal_map_scale,
  material_clearcoatNormal_map_offset,
  material_clearcoatNormal_map_rotation,
  material_clearcoatNormal_scale,
  
  material_dispersion,
  
  material_specular_map_texture,
  material_specular_map_texCoord,
  material_specular_map_scale,
  material_specular_map_offset,
  material_specular_map_rotation,
  material_specular_factor,
  
  material_specularColor_map_texture,
  material_specularColor_map_texCoord,
  material_specularColor_map_scale,
  material_specularColor_map_offset,
  material_specularColor_map_rotation,
  material_specularColor_factor,
  
  material_thickness_map_texture,
  material_thickness_map_texCoord,
  material_thickness_map_scale,
  material_thickness_map_offset,
  material_thickness_map_rotation,
  material_thickness_factor,
  
  material_attenuationDistance,
  material_attenuationColor,
  
  material_transmission_map_texture,
  material_transmission_map_texCoord,
  material_transmission_map_scale,
  material_transmission_map_offset,
  material_transmission_map_rotation,
  material_transmission_factor,
  
  light_position,
  light_direction_model_space,
  light_direction_view_space,
  light_color,
  light_decay_start,
  light_cutoff,
  light_intensity,
  flare_size,
  dust_particle_size,
  dust_particle_color,
  view_space_model_origin,
  mvp,
  invp,
  invmvp,
  invmvp_no_translate,
  model_view_inverse_transpose,
  model_inverse_transpose,
  model_view,
  model_matrix,
  projection_matrix,
  camerapos_model_space,
  viewport,
  diffusetexture,
  speculartexture,
  reflectioncubetexture,
  shadow_mvp1,
  shadow_mvp2,
  shadow_mvp3,
  shadowtexture1,
  shadowtexture2,
  shadowtexture3,
  lightmaptexture,
  gbuffer_frame,
  gbuffer_depth,
  depth_frame,
  volumetric_environment_frame,
  render_frame,
  absolute_time,
  fog_near,
  fog_far,
  fog_density,
  fog_color,
  fog_scale,
  density_premultiplied_exponential,
  density_premultiplied_squared,
  slice_depth_scale,
  particle_origin,
  bone_transforms,
  rim_color,
  rim_power,
  fade_color,
  NUM_SHADER_VALUES
};

bool IsShaderValueName(int index, const char* szName);
const char* getShaderValueName(int index);

class KRReflectedObject
{
public:
  bool getShaderValue(const KRCamera* camera, ShaderValue value, ShaderValueType type, void* output) const;
  virtual bool getImageBinding(const std::string& name, const KRTextureBinding** binding, KRSampler** sample) const;
protected:
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, bool* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, int32_t* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, int64_t* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, float* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, double* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Vector2* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Vector3* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Vector4* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Matrix2* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Matrix2x3* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, hydra::Matrix4* output) const;
  virtual bool getShaderValue(const KRCamera* camera, ShaderValue value, KRResourceBinding* output) const;
};
