--------------------------------------
--                                  --
-- The Geyser Layout Manager by guy --
--                                  --
--------------------------------------

--- This function sets the constraints of a window.
-- It doesn't mess with anything other than positioning data.  It
-- creates get_x(), get_y(), get_width(), and get_height() functions
-- for 'window'
-- @param window The window to create the constraints for.
-- @param cons A table that holds the constraints.
-- @param container A table that holds maximum position values and
-- represents the dimensions of the "window" that holds whatever
-- widget is being created.
function Geyser.set_constraints (window, cons, container)
   oldlocale = os.setlocale(nil, "numeric")
   os.setlocale("C", "numeric")
   -- If container is nil then by default it is the dimensions of the main window
   container = container or Geyser
   
   -- GENERATE CONSTRAINT AWARE POSITIONING FUNCTIONS
   -- Parse the position constraints to generate functions that will get
   -- window dimensions according to those constraints. Also, update position
   -- information.  The order that the dimensions are specified in the for
   -- loop is important so that get_x() and get_y() are defined before they
   -- needed by width and height.
   for _,v in ipairs{"x", "y", "width", "height"} do
      local getter = "get_" .. v -- name of the function to calculate the

      -- if passed a number assume pixels are meant
      if type(cons[v]) == "number" then
         cons[v] = string.format("%dpx", cons[v])
      end
      
      -- Parse the constraint
      if string.find(cons[v], "%%") then
         -- This handles dimensions as a percentage of the container.
         -- Negative percentages are converted to the equivalent positive.
         --------------------------------------------------------------   

         -- scale is a value between 0 and 1   
         local scale = tonumber((string.gsub(cons[v], "%%", ""))) / 100.0
         if scale < 0 then
            scale = 1 + scale
         end
         local dim = ""
         local min, max = 0,0

         if v == "x" then
            min = "container.get_x()"
            max = "container.get_width()"
         elseif v == "width" then
            max = "container.get_width()"
         elseif v == "y" then
            min = "container.get_y()"
            max = "container.get_height()"
         else
            max = "container.get_height()"
         end
         
         -- Define the getter function
         -- Heiko: on European locales this leads to compile errors because
		 --        scale will be "0,5" instead of "0.5"-> syntax error
		 --        Need to find out if there's more such cases in Geyse
		 --        Need to find out if there's more such cases in Geyser
		 h_scale = tostring(scale)
		 local src = "local self,container = ...  return function () return " .. min .. " + (" .. h_scale .. " * " .. max .. ") end"
         
         -- compile the getter
         window[getter] = assert(loadstring(src, "getter for " .. v))(window,container)
         
      else
         -- This handles absolute positioning and character positioning
         -- Negative values indicated positioning from the anti-origin.
         -- Pre: cons[v] must contain "px" or "c"
         --------------------------------------------------------------
         
         -- Create default values
         local x_mult, y_mult = 1,1 -- by default assume not "c"
         local negative = string.find(cons[v], "-") or false -- detect "negative" 0
         
         -- As is, font size is considered a constraint
         if string.find(cons[v], "c") then
            x_mult, y_mult = calcFontSize(window.fontSize)
         end
         
         local pos = tonumber((string.gsub(cons[v], "%a", "")))
         local max = 0
         local min = 0

         if v == "x" then
            min = "container.get_x()"
            pos = x_mult * pos
         elseif v == "width" then
            pos = x_mult * pos
         elseif v == "y" then
            min = "container.get_y()"
            pos = y_mult * pos
         else
            pos = y_mult * pos
         end

         -- Treat negative values differently
         if negative then
            if v == "x" then
               min = "container.get_x()"
               max = "container.get_width()"
            elseif v == "width" then
               min = "container.get_x()"
               max = "container.get_width()"
               pos = string.format("(%d - self:get_x())", pos)
            elseif v == "y" then 
               min = "container.get_y()"
               max = "container.get_height()"
            else -- v == "height"
               min = "container.get_y()"
               max = "container.get_height()"
               pos = string.format("(%d - self:get_y())", pos)
            end
         end

         -- Define the getter function
         local src = "local self, container = ... return function () return " .. max .. " + " .. min .. " + " .. pos .. " end"

         -- compile the getter
         window[getter] = assert(loadstring(src, "getter for " .. v))(window, container)
      end
      
      -- Here the actual value of the dimension is set according to the
      -- constraints requested.
      --window[v] = window[getter]()
   end -- END for that generates POSITION FUNCTIONS
   os.setlocale(oldlocale, "numeric")
   window:reposition()
end
