require "set"

class Window
  include Widget

  @windows = Set.new

  class << self
    def register(window)
      @windows << window
    end

    def remove(window)
      @windows.delete(window)
    end
  end

  def initialize
    super
    @programs = {}
    load_shaders
    Window.register(self)
  end

  def close
    Window.remove(self)
  end

  private

  def load_shaders
    program_sources = {
      text: ["text.v.glsl", "text.f.glsl"],
      basic: ["basic.v.glsl", "basic.f.glsl"],
      rect: ["rect.v.glsl", "basic.f.glsl"],
    }

    program_sources.each do |program, (v_src_fname, f_src_fname)|
      v_src = Runtime.read(:shader, v_src_fname)
      v_shader = GLShader.new(:vertex, v_src)
      v_shader or raise "Could not find shader #{v_src_fname}"

      f_src = Runtime.read(:shader, f_src_fname)
      f_shader = GLShader.new(:fragment, f_src)
      f_shader or raise "Could not find shader #{f_src_fname}"

      uniforms = (v_src + f_src).lines.map do |line|
        if line =~ /\buniform\s.*\s(\S+);/
          $1
        end
      end.compact

      @programs[program] = GLProgram.new(v_shader, f_shader,
                                         uniforms: uniforms)
    end
  end
end
