#include "EnvironmentShader.hpp"
#include <fstream>
#include <string>
#include "Globals.hpp"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

using namespace SH;

EnvironmentShader::EnvironmentShader()
{
}

EnvironmentShader::~EnvironmentShader()
{
}

void EnvironmentShader::init()
{
  ShTextureCube<ShColor4f> cubemap;

  std::string imageNames[6] = {"left", "right", "top", "bottom", "back", "front"};

  {
    ShImage image;
    for (int i = 0; i < 6; i++) {
      image.loadPng(std::string(SHMEDIA_DIR "/envmaps/aniroom/") + imageNames[i] + ".png");
      ShTexture2D<ShColor4f> face(image.width(), image.height());
      face.load(image);
      cubemap.set(static_cast<ShCubeDirection>(i), face);
    }
  }

  vsh = SH_BEGIN_VERTEX_PROGRAM {
    ShInputNormal3f normal;
    ShInputTexCoord2f texture;
    ShInputPosition4f pos;

    ShOutputNormal3f out_normal;
    ShOutputPoint3f out_posEye;
    ShOutputPosition4f out_posDevice;

    out_posEye = (Globals::mv | pos)(0,1,2);
    out_posDevice = Globals::mvp | pos;
    out_normal = Globals::mv | normal;

  } SH_END_PROGRAM;

  ShAttrib1f Ks(1.0);
  ShAttrib1f roughness(0.1);
  ShColor3f lightColor(1, 1, 1);

  fsh = SH_BEGIN_FRAGMENT_PROGRAM {
    ShInputNormal3f normal;
    ShInputPoint3f posEye;
    ShInputPosition4f p;

    ShOutputColor4f out_color;

       out_color =
    cubemap(normalize(reflect(normalize(normal), normalize(-posEye))));

  } SH_END_PROGRAM;

}

void EnvironmentShader::apply()
{
  shBindShader(vsh);
  shBindShader(fsh);
}

void EnvironmentShader::vertex(const SH::ShPoint4f& n, // normal
                               const SH::ShPoint4f& t, // tangent
                               const SH::ShPoint4f& tex, // texture
                                                         // coordinates
                               const SH::ShPoint4f& t2, // secondary
                                                        // tangent
                               const SH::ShPoint4f& v // vertex
                               )
{
  pushSmAttrib(n);
  pushSmAttrib(tex);
  pushSmVertex(v);
}

// Instantiate the shader
EnvironmentShader environmentShader;

