local super = require "Formatter"

DateFormatter = super:new()

-- TODO: Move these.
Duration.year = Duration:get(1)
Duration.quarter = Duration:get(0, 3)
Duration.month = Duration:get(0, 1)
Duration.day = Duration:get(0, 0, 1)

local _templates = {
    { 'year-month-day-long', 'YMMMMd', Duration.day },
    { 'year-month-day-abbreviated', 'YMMMd', Duration.day },
    { 'year-month-day-abbreviated hour-12', 'YMMMdha' },
    { 'year-month-day-abbreviated hour-12-minute', 'YMMMdhm' },
    { 'year-month-day-abbreviated hour-24-minute', 'YMMMdHm' },
    { 'year-month-day-numeric', 'YMd', Duration.day },
    { 'year-month-day-numeric hour-12', 'YMdha' },
    { 'year-month-day-numeric hour-12-minute', 'YMdhm' },
    { 'year-month-day-numeric hour-24-minute', 'YMdHm' },
    { false },
    { 'month-day-long', 'MMMMd', Duration.day },
    { 'month-day-abbreviated', 'MMMd', Duration.day },
    { 'month-day-abbreviated hour-12', 'MMMdha' },
    { 'month-day-abbreviated hour-12-minute', 'MMMdhm' },
    { 'month-day-abbreviated hour-24-minute', 'MMMdHm' },
    { 'month-day-numeric', 'Md', Duration.day },
    { 'month-day-numeric hour-12', 'Mdha' },
    { 'month-day-numeric hour-12-minute', 'Mdhm' },
    { 'month-day-numeric hour-24-minute', 'MdHm' },
    { false },
    { 'hour-12', 'ha' },
    { 'hour-12-minute', 'hm' },
    { 'hour-12-minute-second', 'hms' },
    { 'hour-24-minute', 'Hm' },
    { 'hour-24-second', 'Hms' },
    { false },
    { 'year-month-long', 'YMMMM', Duration.month },
    { 'year-month-abbreviated', 'YMMM', Duration.month },
    { 'year-month-numeric', 'YM', Duration.month },
    { 'year-quarter', 'YQQQ', Duration.quarter },
    { 'year', 'Y', Duration.year },
}

local defaults = {
    template = 'year-month-day-long',
}

local nilDefaults = {
}

local function _getTemplate(name)
    if name then
        for index = 1, #_templates do
            local template = _templates[index]
            if template[1] == name then
                return template
            end
        end
    end
    return _getTemplate(defaults.template)
end

function DateFormatter:new(template)
    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
    
    if template then
        self:notUndoably(function()
            self:setTemplate(template)
        end)
    end
    
    return self
end

-- NOTE: Version 1.1.3 and earlier saved 'date' and 'time' properties.
function DateFormatter:unarchiveDate(archived)
    if unarchive(archived) then
        self:setTemplate('year-month-day-abbreviated')
    else
        self:setTemplate(nil)
    end
end
function DateFormatter:unarchiveTime(archived)
    if unarchive(archived) then
        local components = {}
        components[#components + 1] = self:getTemplate()
        components[#components + 1] = 'time-12'
        self:setTemplate(table.concat(components, ' '))
    end
end

local function _getDemoDate()
    local date = Date:now()
    date = Date:get(date:year(), 9, 6, 16, 0, 0)
    return date
end

function DateFormatter:getSubclasses()
    return {
        { DateFormatter, 'Date/Time' },
    }
end

function DateFormatter:getTemplates()
    local result = {}
    local date = _getDemoDate()
    for index = 1, #_templates do
        local template = _templates[index]
        if template[1] then
            local formatter = DateStringFormatter:template(template[2])
            result[#result + 1] = { template[1], formatter:format(date) }
        else
            result[#result + 1] = { false }
        end
    end
    return result
end

function DateFormatter:getFormatter()
    return DateStringFormatter:deferredTemplate()
end

function DateFormatter:getArguments()
    return {
        _getTemplate(self:getTemplate())[2],
    }
end

function DateFormatter:getInspectors()
    local list = List:new()
    local inspector, hook
    inspector = Inspector:new{
        title = 'Format',
        type = 'Class',
        constraint = function()
            local date = _getDemoDate()
            local formatter = DateStringFormatter:deferredTemplate()
            local templateNames = {}
            for index = 1, #_templates do
                local template = _templates[index]
                templateNames[index] = { template[1], template[1] and formatter:format(date, template[2]) }
            end
            return templateNames
        end,
    }
    inspector:addHook(self:getPropertyHook('template'))
    list:add(inspector)
    return list
end

function DateFormatter:getTemplate()
    return self:getProperty('template')
end

function DateFormatter:setTemplate(template)
    self:setProperty('template', template)
end

function DateFormatter:getInterval()
    return _getTemplate(self:getTemplate())[3]
end

function DateFormatter:__eq(other)
    return Object.isa(other, DateFormatter) and other:getTemplate() == self:getTemplate()
end

return DateFormatter
