#ifndef PW_VISUAL_SHADER_HPP
#define PW_VISUAL_SHADER_HPP

#include <pw/core/globals.hpp>
#include <pw/core/matrix.hpp>
#include <pw/core/vector.hpp>
#include <pw/core/debug.hpp>

#include <map>

namespace pw {

class shader {
public:

	shader();
    ~shader();

	enum code_type {
		vertex,
		fragment,
		geometry,
		compute
	};

    void set_source(const std::string& c,code_type t) { _source[t] = c; }
	std::string source(code_type t) { return _source[t]; }

//	void set_attributes(const std::vector<std::string> > &attributes);

	bool ready() const;

	shader& bind(int location,float v);
	shader& bind(int location,matrix4x4f const & v);
	shader& bind(int location,vector4f const & v);

	int uniform_location(std::string const & name) const;

	template<typename T>
	shader & bind(std::string const & name, T&& value)
	{
		int location = uniform_location(name);
		if (location >= 0)
			return bind(location, std::forward<T>(value));
		else
			debug::e() << "missing uniform: "<< name;
		return *this;
	}

	bool build();

    void use();

protected:

	std::map<code_type,std::string> _source;

	struct impl;
	std::unique_ptr<impl> _impl;

};

}

#endif
