var gMeShadeBuilder = null;

function glTypeString(gl, type) {
	if (type == gl.BOOL) {
		return "bool";
	}
	else if (type == gl.BOOL_VEC2) {
		return "bvec2";
	}
	else if (type == gl.BOOL_VEC3) {
		return "bvec3";
	}
	else if (type == gl.BOOL_VEC4) {
		return "bvec4";
	}
	else if (type == gl.INT) {
		return "int";
	}
	else if (type == gl.INT_VEC2) {
		return "ivec2";
	}
	else if (type == gl.INT_VEC3) {
		return "ivec3";
	}
	else if (type == gl.INT_VEC4) {
		return "ivec4";
	}
	else if (type == gl.FLOAT) {
		return "float";
	}
	else if (type == gl.FLOAT_VEC2) {
		return "vec2";
	}
	else if (type == gl.FLOAT_VEC3) {
		return "vec3";
	}
	else if (type == gl.FLOAT_VEC4) {
		return "vec4";
	}
	else if (type == gl.FLOAT_MAT2) {
		return "mat2";
	}
	else if (type == gl.FLOAT_MAT3) {
		return "mat3";
	}
	else if (type == gl.FLOAT_MAT4) {
		return "mat4";
	}
	else if (type == gl.SAMPLER_2D) {
		return "sampler2D";
	}
	else if (type == gl.SAMPLER_CUBE) {
		return "samplerCube";
	}
	else {
		return "UNKNOWN";
	}
}

function fillProgramSources() {
	var psrc = gMeShadeBuilder.getProgramSources();
	$("#VERTEX_SHADER_SOURCE"  ).html(psrc[0]);
	$("#FRAGMENT_SHADER_SOURCE").html(psrc[1]);

	var plog = gMeShadeBuilder.getProgramLog();
	$("#PROGRAM_LOG").html(plog);
}

function uniformScalar(name, value) {
	var uniforms = gMeShadeBuilder.getProgramUniforms();
	var src = uniforms[name];
	if (!src) return;
	if (src.builtin) return;

	src.value = value;

	var nf = { };
	nf[src.name] = src;
	gMeShadeBuilder.setUniforms(nf);
}

function uniformVec(name, component, value) {
	var uniforms = gMeShadeBuilder.getProgramUniforms();
	var src = uniforms[name];
	if (!src) return;
	if (src.builtin) return;

	src.value[component] = value;

	var nf = { };
	nf[src.name] = src;
	gMeShadeBuilder.setUniforms(nf);
}

function uniformMat(name, component, value) {
	var uniforms = gMeShadeBuilder.getProgramUniforms();
	var src = uniforms[name];
	if (!src) return;
	if (src.builtin) return;

	src.value[component] = value;

	var nf = { };
	nf[src.name] = src;
	gMeShadeBuilder.setUniforms(nf);
}

function createScalarCheckbox(name, typeName) {
	var html = "";

	html += "<td>" + typeName + "</td>";

	html += "<td>";
	html += "<table>";
	html += "<tr>";
	html += "<td>";
	html += "<input type='checkbox' size='4' " + ((uniform.value) ? ("checked") : ("")) + "'onchange='uniformScalar(\"" + uniform.name + "\", ((this.value) ? (1) : (0)))' />";
	html += "</td>";
	html += "</tr>";
	html += "</table>";
	html += "</td>";

	return html;
}

function createScalarEdit(uniform, typeName, parseFuncName) {
	var html = "";

	html += "<td>" + typeName + "</td>";

	html += "<td>";
	html += "<table>";
	html += "<tr>";
	html += "<td>";
	html += "<input type='text' size='4' value='" + uniform.value + "' onchange='uniformScalar(\"" + uniform.name + "\", " + parseFuncName + "(this.value))' />";
	html += "</td>";
	html += "</tr>";
	html += "</table>";
	html += "</td>";

	return html;
}

function createVectorCheckbox(uniform, typeName, size) {
	var html = "";

	html += "<td>" + typeName + "</td>";

	html += "<td>";
	html += "<table>";
	html += "<tr>";
	var value = uniform.value;
	for (var i=0; i<size; ++i) {
		html += "<td>";
		html += "<input type='checkbox' " + ((uniform.value) ? ("checked") : ("")) + "' onchange='uniformVec(\"" + uniform.name + "\", " + i + ", ((this.value) ? (1) : (0)))' />";
		html += "</td>";
	}
	html += "</tr>";
	html += "</table>";
	html += "</td>";

	return html;
}

function createVectorEdit(uniform, typeName, size, parseFuncName) {
	var html = "";

	html += "<td>" + typeName + "</td>";

	html += "<td>";
	html += "<table>";
	html += "<tr>";
	var value = uniform.value;
	for (var i=0; i<size; ++i) {
		html += "<td>";
		html += "<input type='text' size='4' value='" + value[i] + "' onchange='uniformVec(\"" + uniform.name + "\", " + i + ", " + parseFuncName + "(this.value))' />";
		html += "</td>";
	}
	html += "</tr>";
	html += "</table>";
	html += "</td>";

	return html;
}

function createMatrixEdit(uniform, typeName, size, parseFuncName) {
	var html = "";

	html += "<td>" + typeName + "</td>";

	html += "<td>";
	html += "<table>";
	var value = uniform.value;
	for (var i=0; i<size; ++i) {
		html += "<tr>";
		for (var j=0; j<size; ++j) {
			html += "<td>";
			html += "<input type='text' size='4' value='" + value[i+j*4] + "' onchange='uniformMat(\"" + uniform.name + "\", " + (i+j*4) + ", " + parseFuncName + "(this.value))' />";
			html += "</td>";
		}
		html += "</tr>";
	}
	html += "</table>";
	html += "</td>";

	return html;
}

function createUniform(gl, uniform) {
	var name = uniform.name;
	var type = uniform.type;
	var html = "";

	html += "<tr>";
	html += "<td>" + name + "</td>";

	if (type == gl.BOOL) {
		html += createScalarCheckbox(uniform, "bool");
	}
	else if (type == gl.BOOL_VEC2) {
		html += createVectorCheckbox(uniform, "bvec2", 2);
	}
	else if (type == gl.BOOL_VEC3) {
		html += createVectorCheckbox(uniform, "bvec3", 3);
	}
	else if (type == gl.BOOL_VEC4) {
		html += createVectorCheckbox(uniform, "bvec4", 4);
	}
	else if (type == gl.INT) {
		html += createScalarEdit(uniform, "int", "parseInt");
	}
	else if (type == gl.INT_VEC2) {
		html += createVectorEdit(uniform, "ivec2", 2, "parseInt");
	}
	else if (type == gl.INT_VEC3) {
		html += createVectorEdit(uniform, "ivec3", 3, "parseInt");
	}
	else if (type == gl.INT_VEC4) {
		html += createVectorEdit(uniform, "ivec4", 4, "parseInt");
	}
	else if (type == gl.FLOAT) {
		html += createScalarEdit(uniform, "float", "parseFloat");
	}
	else if (type == gl.FLOAT_VEC2) {
		html += createVectorEdit(uniform, "vec2", 2, "parseFloat");
	}
	else if (type == gl.FLOAT_VEC3) {
		html += createVectorEdit(uniform, "vec3", 3, "parseFloat");
	}
	else if (type == gl.FLOAT_VEC4) {
		html += createVectorEdit(uniform, "vec4", 4, "parseFloat");
	}
	else if (type == gl.FLOAT_MAT2) {
		html += createMatrixEdit(uniform, "mat2", 2, "parseFloat");
	}
	else if (type == gl.FLOAT_MAT3) {
		html += createMatrixEdit(uniform, "mat3", 3, "parseFloat");
	}
	else if (type == gl.FLOAT_MAT4) {
		html += createMatrixEdit(uniform, "mat4", 4, "parseFloat");
	}
	else {
		return "";
	}

	//html += "<td>" + uniform.desc + "</td>";
	html += "</tr>";

	return html;
}

function fillUniforms() {
	var gl = gMeShadeBuilder.glContext;

	var uniforms = gMeShadeBuilder.getProgramUniforms();
	var html = "";

	html += "<table border='0'>";
	//html += "<tr><th>Name</th><th>Type</th><th>Value</th><th>Description</th></tr>";
	html += "<tr><th>Name</th><th>Type</th><th>Value</th></tr>";
	for (var u in uniforms) {
		var src = uniforms[u];
		if (!src.builtin) {
			html += createUniform(gl, src);
		}
	}
	html += "</table>";

	$("#UNIFORMS").html(html);
}

function setSampler(name) {
	var url = $("#SAMPLER_" + name + "_EDIT").val();
	var samplers = { };
	samplers[name] = url;
	gMeShadeBuilder.setSamplers(samplers);
}

function fillSamplers() {
	var gl = gMeShadeBuilder.glContext;

	var samplers = gMeShadeBuilder.getProgramSamplers();
	var html = "";

	html += "<table border='0'>";
	html += "<tr><th>Name</th><th>Type</th><th>URL</th></tr>";
	for (var s in samplers) {
		var src = samplers[s];
		html += "<tr><td>" + s + "</td><td>" + glTypeString(gl, src.type) + "</td><td><input type='text' id='SAMPLER_" + s + "_EDIT' value='" + src.url + "' />";
		html += "&nbsp;<input type='button' value='Load' onclick='setSampler(\"" + s + "\")'></td></tr>";
	}
	html += "</table>";

	$("#SAMPLERS").html(html);
}

function fillPredefinedUniforms() {
	var gl = gMeShadeBuilder.glContext;

	var uniforms = gMeShadeBuilder.getPredefinedUniforms();
	var html = "";

	html += "<table border='0'>";
	html += "<tr><th>Name</th><th>Type</th><th>Description</th></tr>";
	for (var u in uniforms) {
		var src = uniforms[u];
		html += "<tr><td>" + u + "</td><td>" + glTypeString(gl, src.type) + "</td><td>" + src.desc + "</td></tr>";
	}
	html += "</table>";

	$("#PREDEFINED_UNIFORMS").html(html);
}

function fillPredefinedAttributes() {
	var attribs = gMeShadeBuilder.getPredefinedAttributes();
	var html = "";

	html += "<table border='0'>";
	html += "<tr><th>Name</th><th>Size</th></tr>";
	for (var a in attribs) {
		var src = attribs[a];
		html += "<tr><td>" + src.name + "</td><td>" + src.size + "</td></tr>";
	}
	html += "</table>";

	$("#VSHADER_ATTRIBUTES").html(html);
}

function validateProgram() {
	var vsrc = $("#VERTEX_SHADER_SOURCE"  ).val();
	var fsrc = $("#FRAGMENT_SHADER_SOURCE").val();
	var ret = gMeShadeBuilder.validateProgramSources(vsrc, fsrc);
	$("#PROGRAM_LOG").html(ret.log);
}

function applyProgram() {
	var vsrc = $("#VERTEX_SHADER_SOURCE"  ).val();
	var fsrc = $("#FRAGMENT_SHADER_SOURCE").val();

	var ret = gMeShadeBuilder.setProgramSources(vsrc, fsrc);
	$("#PROGRAM_LOG").html(ret.log);

	fillUniforms();
	fillSamplers();
}

function clearLog() {
	$("#PROGRAM_LOG").html("");
}

function loadMesh() {
	var url = $("#MESH_FILE_PATH").val();
	//gMeShadeBuilder.loadMesh("file://" + url);
	gMeShadeBuilder.loadMesh(url);
}

function meshLoaded() {
	var info = gMeShadeBuilder.getMeshInfo();
	$("#MESH_ATTRIBUTES").html(info.vertexAttributes.join(", "));
	$("#MESH_VERTCOUNT").html(info.verticesCount);
	$("#MESH_TRICOUNT").html(info.trianglesCount);

	fillPredefinedAttributes();
}

function resetView() {
	gMeShadeBuilder.resetView();
}

function changeBackgroundColor(color) {
	var r = parseInt(color.substr(1, 2), 16) / 255.0;
	var g = parseInt(color.substr(3, 2), 16) / 255.0;
	var b = parseInt(color.substr(5, 2), 16) / 255.0;
	gMeShadeBuilder.setBackgroundColor(r, g, b);
}

function generateCode() {
	var code = gMeShadeBuilder.buildPage();
	$("#GENERATED_CODE_JSON").val(code.srcJSON);
	$("#GENERATED_CODE_HTML").val(code.srcHTML);
}

function ensureCanvasSize() {
	var canvas = document.getElementById("SGL_CANVAS1");
	canvas.width  = canvas.clientWidth;
	canvas.height = canvas.clientHeight;
	if (gMeShadeBuilder) {
		gMeShadeBuilder.refresh();
	}
}

function drawTriad() {
	gMeShadeBuilder.drawTriad = $("#DRAW_TRIAD").attr('checked');
}

function drawBBox() {
	gMeShadeBuilder.drawBBox = $("#DRAW_BBOX").attr('checked');
}

function init() {
	gMeShadeBuilder = new MeShadeBuilder("SGL_CANVAS1");
	gMeShadeBuilder.onload = meshLoaded;
	fillProgramSources();
	fillPredefinedUniforms();
	fillPredefinedAttributes();
	fillUniforms();
	fillSamplers();

	ensureCanvasSize();
};

