﻿#include "GL/glew.h"
#include "GLFW/glfw3.h"
#include "glm/glm.hpp"
#include "./glm/ext.hpp" // perspective, translate, rotate
#include <iostream>
#include "utils.h"
#include "stb_imageloader.h"
using namespace std;
int choice = 0;
int direction = 0;
#define numVAOs 1
#define numVBOs 2
// allocate variables used in display() function, so that they won�t need to be allocated during rendering
GLuint mvLoc, projLoc;
int width, height;
float aspect;
glm::mat4 pMat(1.0), vMat(1.0), mMat(1.0), mvMat(1.0);
void setupVertices(void);
GLuint renderingProgram, rendProg;
GLuint vao[numVAOs];
GLuint vbo[numVBOs];
static void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
	static int last = 0;
	if (key == GLFW_KEY_A)
	{
		cout << "A pressed" << last << endl;
		choice = 0;
	}
	if (key == GLFW_KEY_S)
	{
		cout << "S pressed" << last << endl;
		choice = 1;
	}
}


void getWinSizeCB(GLFWwindow* window, int width, int height)
{
	glViewport(0, 0, width, height);
}



void init(GLFWwindow* window) {
	GLuint tex = 0;
	int x, y, n;
	int force_channels = 4; //RGB and A
	char filename[] = "frog.png";
	unsigned char* image_data = stbi_load(filename , &x, &y, &n, force_channels);  //x = x dimemsions, y= ydims, 
	if (!image_data)
	{
		cout << "error: could not load " << filename << endl;

	}
	// copy image into ogl buffer - stick to images power of 2 high and wide
	glGenTextures(1, &tex);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, tex);
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image_data);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	renderingProgram = createShaderProgram("vertShader.glsl","fragShader.glsl"); //load, compile, create, attach and link shader programmes done here
	
	rendProg = createShaderProgram("vertShader.glsl", "fragShader2.glsl");
	
	glfwGetFramebufferSize(window, &width, &height); //need these to fit clip space to window
	aspect = (float)width / (float)height;
	glfwSetFramebufferSizeCallback(window, getWinSizeCB);
	setupVertices(); //initial vertices x,y,z values
	glEnable(GL_DEPTH_TEST);
}
void display(GLFWwindow* window, double currentTime)
//runs 60 times a second by default in glfw - see main loop
{
	glClear(GL_DEPTH_BUFFER_BIT);
	glClearColor(0.8, 0.8, 0.9, 1.0);
	glClear(GL_COLOR_BUFFER_BIT);
	
	if (choice == 0) {
		glUseProgram(rendProg); //specify linked program to use
		mvLoc = glGetUniformLocation(rendProg, "mv_matrix");
		projLoc = glGetUniformLocation(rendProg, "proj_matrix");
	}
	else {
		glUseProgram(renderingProgram); //specify linked program to use
		mvLoc = glGetUniformLocation(renderingProgram, "mv_matrix");
		projLoc = glGetUniformLocation(renderingProgram, "proj_matrix");
	}
	//get a reference to the shader variable Vcol
	//GLuint VcolLoc = glGetUniformLocation(renderingProgram, "Vcol");

	// copy perspective and MV matrices to corresponding uniform variables
	glUniformMatrix4fv(mvLoc, 1, GL_FALSE, glm::value_ptr(mvMat));
	glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(pMat));
	// adjust OpenGL settings
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]); //house mesh bound to VBO
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]); //house mesh bound to VBO
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(1);
	glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
	int xOffset = 0, yOffset = 0;
	
	float houseCols[18] = {
	1.0,0.0,0.0,
	1.0,1.0,0.0,
	174.0 / 255.0,85.0 / 255.0,186.0 / 255.0,
	0.0,1.0,0.0,
	0.0,0.0,1.0,
	233.0 / 255.0,66.0 / 255.0,17.0 / 255.0
	};

	
		glDrawArrays(GL_TRIANGLES, 0, 6);  //draw a quad

	

}

int main(void) {
	if (!glfwInit()) { exit(EXIT_FAILURE); }
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
	GLFWwindow* window = glfwCreateWindow(600, 600, "glfw window", NULL, NULL);
	glfwSetKeyCallback(window, key_callback);
	glfwMakeContextCurrent(window);
	if (glewInit() != GLEW_OK) { exit(EXIT_FAILURE); }
	glfwSwapInterval(1);
	init(window);
	while (!glfwWindowShouldClose(window)) {
		display(window, glfwGetTime());
		glfwSwapBuffers(window);
		glfwPollEvents();
	}
	glfwDestroyWindow(window);
	glfwTerminate();
	exit(EXIT_SUCCESS);
}


void setupVertices(void) {

	float quad[18] = {
		//A House
			 -1.0, 1.0, 0.0,//front 
			 1.0, -1.0, 0.0,
			 -1.0, -1.0, 0.0,
			-1.0, 1.0, 0.0,
			1.0, -1.0, 0.0,
			1.0, 1.0, 0.0
	};

		float quadTex[12] = {

			0.0, 1.0,
			1.0, 0.0,
			0.0, 0.0,
			0.0, 1.0,
			1.0, 0.0,
			1.0, 1.0 };
			
		
	//initialse VAO and VBOs
	glGenVertexArrays(numVAOs, vao); //we will use one VAO
	glBindVertexArray(vao[0]);
	glGenBuffers(numVBOs, vbo);//we have one VBO
	glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);//first VBO
	glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
	glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);//2nd  VBO
	glBufferData(GL_ARRAY_BUFFER, sizeof(quadTex), quadTex, GL_STATIC_DRAW);

}