local super = require "TableColumn"

NumberColumn = super:new()

local defaults = {
    halign = 1,
    valign = 0.5,
}

local nilDefaults = {
    'value', 'formatter', 'paint', 'font',
}

local getterNames = {'value', 'formatter', 'paint', 'font', 'halign', 'valign'}

local inspectorInfo = {
    {'KeyArtifact', {'value'}, 'Value'},
}
local moreInspectorInfo = {
    {'Color', {'getPaint:setPaint', custom = 'hasExplicitPaint:'}, 'Color'},
    {'Font', {'getFont:setFont', custom = 'hasExplicitFont:'}, 'Font'},
    {'Alignment', {'halign'}, 'Alignment'},
}

function NumberColumn:new()
    self = super.new(self)
    
    for k, v in pairs(defaults) do
        self:addProperty(k, v)
    end
    for _, k in pairs(nilDefaults) do
        self:addProperty(k)
    end
    
    self.stamp = FormattedValueTextStamp
    self.getterNames = getterNames
    self.inspectorInfo = inspectorInfo
    
    local validator = function(formatter)
        return formatter == nil or Object.isa(formatter, NumberFormatter)
    end
    self:getPropertyHook('formatter'):setValidator(validator)
    
    -- TODO: rebuild any open inspectors, but do it less awkwardly.
    local formatterHook = self:getPropertyHook('formatter')
    self._formatterObserver = function(sender)
        if sender == formatterHook then
            sender = self
        end
        self:invalidate(sender)
    end
    formatterHook:removeObserver(self)
    formatterHook:addObserver(self._formatterObserver)
    
    return self
end

function NumberColumn:unarchived()
    local dataset = self:getDataset()
    if dataset then
        if self:getProperty('value') == nil then
            local avoidingFields = self:peerPropertyKeyArtifactValues(NumberColumn, 'value')
            local field = dataset:pickField('number', avoidingFields)
            if field then
                self:setProperty('value', KeyArtifact:new(field))
                self:setTitle(field)
            end
        end
    end
    super.unarchived(self)
end

function NumberColumn:getInspectors()
    local list = super.getInspectors(self)
    local inspector, hook
    inspector = Inspector:new{
        title = 'Format',
        type = 'Class',
        constraint = function()
            return self:getFormatters()
        end,
    }
    hook = Hook:new(
        function()
            local formatter = self:getFormatter()
            if formatter then
                return _G[formatter:class()]
            end
        end,
        function(value)
            local formatter
            if Object.isa(value, Formatter) then
                formatter = value:new()
                formatter:mirror(self:getFormatter())
            end
            self:setFormatter(formatter)
        end)
    inspector:addHook(hook)
    self:getPropertyHook('formatter'):addObserver(inspector)
    list:add(inspector)
    local formatter = self:getFormatter()
    if formatter and formatter.getInspectors then
        list:add(Inspector:new{
            type = 'List.Group',
            target = function()
                return formatter:getInspectors()
            end,
        })
    end
    for i = 1, #moreInspectorInfo do
        local info = moreInspectorInfo[i]
        list:add(self:createInspector(unpack(info)))
    end
    return list
end

function NumberColumn:getFormatter()
    return self:getProperty('formatter')
end

function NumberColumn:setFormatter(formatter)
    self:setProperty('formatter', formatter)
end

function NumberColumn:getFormatters()
    local formatters = { { nil, 'Auto Format' } }
    appendtables(formatters, {false}, NumberFormatter:getSubclasses())
    return formatters
end

function NumberColumn:getFont()
    return self:getProperty('font') or self:getParent():getLabelFont()
end

function NumberColumn:setFont(value)
    self:setProperty('font', value)
end

function NumberColumn:hasExplicitFont()
    return self:getProperty('font') ~= nil
end

return NumberColumn
