#include <iostream>
#include <Windows.h>
#include "prepare_shader.hpp"
#include <gl/GL.h>
#include <gl/GLU.h>
#include <gl/freeglut.h>
#pragma comment(lib,"glew32.lib")
//ウィンドウの幅と高さ
int width, height;
GLuint buf_points;
GLuint buf_tcoord;
GLuint textureID22;
GLuint textureID44;
GLfloat mproj[16];
GLfloat mmodel[16];
GLuint programID;
      void texture_setting(GLuint* texid, std::vector < GLubyte >& texdata, int TEXWIDTH, int TEXHEIGHT) {
  glGenTextures(1, texid);
  glBindTexture(GL_TEXTURE_2D, *texid);
  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  // テクスチャの割り当て
  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, TEXWIDTH, TEXHEIGHT, 0,
    GL_RGB, GL_UNSIGNED_BYTE, texdata.data());
  // テクスチャを拡大・縮小する方法の指定
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
}
// テクスチャ作成
void create_texture_22() {
  std::vector < GLubyte > texdata;
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 255, 0);
  push_3(texdata, 255, 255, 255);
  push_3(texdata, 0, 255, 255);
  texture_setting(&textureID22, texdata, 2, 2);
  texdata.clear();
}
void create_texture_44() {
  std::vector < GLubyte > texdata;
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  push_3(texdata, 0, 0, 0);
  push_3(texdata, 255, 0, 0);
  texture_setting(&textureID44, texdata, 4, 4);
  texdata.clear();
}
      // シェーダとデータの設定
void init() {
  /////////////////////////////////////////////
  std::vector<GLfloat> points;
  GLfloat v = 0.8;
  push_3(points, -v , -v , 0);
  push_3(points,  v , -v , 0);
  push_3(points, -v ,  v , 0);
  push_3(points,  v ,  v , 0);
  prepare_buffer(&buf_points, points.data(), points.size() * sizeof(GLfloat), GL_STATIC_DRAW);
  /////////////////////////////////////////////
  // テクスチャ座標
  std::vector<GLfloat> texcoord;
  push_2(texcoord, 0, 0);
  push_2(texcoord, 1, 0);
  push_2(texcoord, 0, 1);
  push_2(texcoord, 1, 1);
  prepare_buffer(&buf_tcoord, texcoord.data(), texcoord.size() * sizeof(GLfloat), GL_STATIC_DRAW);
  /////////////////////////////////////////////
  //テクスチャ(画像)作成
  create_texture_22();
  create_texture_44();
  /////////////////////////////////////////////
  GLuint vtxShader;
  GLuint flagShaderR;
  const char* vtxfile = "default.vert";
  const char* fragfileR = "default.frag";
  std::string verr;
  std::string ferr;
  prepare_shader_byfile(&vtxShader, GL_VERTEX_SHADER, vtxfile, &verr);
  prepare_shader_byfile(&flagShaderR, GL_FRAGMENT_SHADER, fragfileR, &ferr);
  std::cout << verr << std::endl;
  std::cout << ferr << std::endl;
  std::string linkerr;
  link_program(&programID, { vtxShader ,flagShaderR }, nullptr, &linkerr);
  loadidentity44(mproj);
  loadidentity44(mmodel);
}
      //描画関数
void disp(void) {
  glViewport(0, 0, width, height);
  glClearColor(0.2, 0.2, 0.2, 1);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glUseProgram(programID);
  GLuint loc_ModelViewMatrix = glGetUniformLocation(programID, "ModelViewMatrix");
  GLuint loc_ProjectionMatrix = glGetUniformLocation(programID, "ProjectionMatrix");
  glUniformMatrix4fv(loc_ModelViewMatrix, 1, GL_FALSE, mmodel);
  glUniformMatrix4fv(loc_ProjectionMatrix, 1, GL_FALSE, mproj);
        GLint loc_tex22 = glGetUniformLocation(programID, "Tex22");
  glUniform1i(loc_tex22, 0);// Texture unit 0
  glActiveTexture(GL_TEXTURE0 + 0); // Texture unit 0
  glBindTexture(GL_TEXTURE_2D, textureID22);
  GLint loc_tex44 = glGetUniformLocation(programID, "Tex44");
  glUniform1i(loc_tex44, 1);// Texture unit 1
  glActiveTexture(GL_TEXTURE0 + 1); // Texture unit 1
  glBindTexture(GL_TEXTURE_2D, textureID44);
      
  {
    auto bind_points = EnableAndBindFArrayBuffer(0, buf_points, 3, GL_FLOAT);
    auto bind_tcoord = EnableAndBindFArrayBuffer(1, buf_tcoord, 2, GL_FLOAT);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
  }
  glUseProgram(0);
  glFlush();
}
      //ウィンドウサイズの変化時に呼び出される
void reshape(int w, int h) {
  width = w; height = h;
  disp();
}
//エントリポイント
int main(int argc, char** argv)
{
  glutInit(&argc, argv);
  glutInitWindowPosition(100, 50);
  glutInitWindowSize(500, 500);
  glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
  glutCreateWindow("sample");
  glutDisplayFunc(disp);
  glutReshapeFunc(reshape);
  glewInit();
  init();
  glutMainLoop();
  return 0;
}