--
-- pixwerx - bare rendering engine binding usage
--

-- we need everything
pw.script:load_all()


print(pw.path.get().executable_path)

-- create a window (remember windows are invisible by default)
local w = pw.window.new()

-- set title
w.title = "pixwerx - bare rendering"

-- set size
w.size = pw.size(640,480)

-- move window
w.position = pw.point(100,100)

-- create a new geometry
local g = pw.geometry()

g.primitive_topology = pw.primitive_topology_type.triangle_list -- meh

z = -5.0
s = 1

-- geometry can only build with indexed facesets
g.vertices:add(pw.vector3:new(-s, s, z)) -- 0
g.vertices:add(pw.vector3:new(-s,-s, z)) -- 1
g.vertices:add(pw.vector3:new( s,-s, z)) -- 2
g.vertices:add(pw.vector3:new( s, s, z)) -- 3

-- 0 --- 3
-- |  \  |
-- 1 --- 2

g.indices:add(0)
g.indices:add(1)
g.indices:add(2)

g.indices:add(2)
g.indices:add(3)
g.indices:add(0)


local mm = pw.matrix4x4:new()
local mv = pw.matrix4x4:new()
local mp = pw.matrix4x4:new()

local s = pw.shader:new()

s:set_source(pw.shader_type.vertex,[[
#version 400
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

in vec3 vertex_p;

void main() {
    gl_Position = projection * view * model * vec4(vertex_p, 1.0);
}
]])

s:set_source(pw.shader_type.fragment,[[
#version 400
uniform vec4 color = vec4(1.0, 0.0, 0.0, 1.0);
out vec4 frag_colour;

void main() {
    frag_colour = color;
}
]])

-- check if the shader can be compiled and linked
if not s:build() then
    print("Error!")
end


-- the renderer for a geometry
local renderer = pw.renderer:new()

if not renderer:create(g) then
    print("couldn't create renderer")
end

-- camera position
local cam_pos = pw.vector3:new(0,0,0)

local model_pos = pw.vector3:new(0,0,0)


local ctx = pw.context:new()

w.on_resize = function(self)
    -- use client_size to resize the viewport
    ctx:set_viewport(pw.rectangle:new(pw.point:new(0,0),self.client_size:cast_to_float()))
end


-- setup a lua callback function as callback
w.on_update = function(self)

    -- set identity on model matrix
    mm:set_identity()

    -- set view matrix with look_at - view matrix is moving the world - hence inverse!
    mv = pw.matrixtransform.look_at(cam_pos,cam_pos + pw.vector3.forward(),pw.vector3.up()):inverse()

    -- compute aspect ratio from canvas size
    aspect_ratio = self.client_size.width / self.client_size.height

    -- create a view frustom for a perspective projection
    mp = pw.matrixtransform.perspective_projection(1.3,aspect_ratio,0.2,100)

    -- just some toying around
    local color_red  = pw.mathf.ping_pong(pw.time.now,1.0)
    local color_green = pw.mathf.ping_pong(pw.time.now + 1,1.0)
    local color_blue = 1.0 - pw.mathf.ping_pong(pw.time.now,1.0)
    local cl = pw.vector4:new( color_red, color_green, color_blue, 1.0 )

    -- bind the shader
    s:use()

    -- update the unifors, currently the slow path
    s:set_uniform_mat4("model",mm)
    s:set_uniform_mat4("view",mv)
    s:set_uniform_mat4("projection",mp)
    s:set_uniform_vec4("color",cl)

    -- draw
    renderer:draw()

end

-- before entering the update loop make the window visible
w.visible = true

-- main update loop
while w:update() do

    -- only check if get a new input
    if pw.input.get().has_input then

        -- somehow works
        if pw.input.get().input_string == 'f' then
            w.fullscreen = not w.fullscreen
        end

        -- keycode for quit
        if pw.input.get().input_string == 'q' then
            break
        end

        -- just to quickly modify speed
        local move_step = 0.05

        -- camera
        if     pw.input.get().input_string == 'w' then
            cam_pos.z = cam_pos.z - move_step
        elseif pw.input.get().input_string == 's' then
            cam_pos.z = cam_pos.z + move_step
        elseif pw.input.get().input_string == 'a' then
            cam_pos.x = cam_pos.x - move_step
        elseif pw.input.get().input_string == 'd' then
            cam_pos.x = cam_pos.x + move_step
        elseif pw.input.get().input_string == 'z' then
            cam_pos.y = cam_pos.y + move_step
        elseif pw.input.get().input_string == 'x' then
            cam_pos.y = cam_pos.y - move_step
        end

        print(cam_pos.x,cam_pos.y,cam_pos.z)

    end

    -- just to check
    if pw.input:get().mouse_button == 1 then

        print("elapsed",t.elapsed)
            t:reset()
        print(pw.input:get().mouse_position.x,pw.input:get().mouse_position.y,w.client_size.width,w.client_size.height)
    end

end
