


local turretList = dataManagerConstructor:new()
local turretDataBase

addEventHandler("onResourceStart", resourceRoot, 
function () 
    turretDataBase = xmlDb:create("turrets")

    --[[
        Loading
    ]]
    
    local turretsDatabaseData = turretDataBase:get("list")
    if turretsDatabaseData then
        turretList:addAllData(turretsDatabaseData.data)
        
        turretList:forEach(function (id, turretData) 
            createTurretBasedOnTurretData (turretData)
        end)
    else
        turretDataBase:insert("list",  {})
    end
	
	local players = getElementsByType("player")
	for i=1, #players do
		local player = players[i]
		if canPlayerModifyTurrets(player) then
			outputChatBox("Hi beta tester! Use the command: #ffffff /turret \n#c8c800to open the turret panel.", player, 200, 200, 0, true)
		end
	end
end, false)


function getTurretListItemName (turretData)
    return turretData.name
end

function openTurretPanel ()
    if canPlayerModifyTurrets (client) then
        addTurretListSubscriber(client)
        return true
    else
        return false, "You do not have permission to open the turret panel."
    end
end
addToWhitelist(openTurretPanel)

function addTurret ()
    if canPlayerModifyTurrets (client) then
        local turretData = {
            name = "<New turret by " .. getPlayerName(client) .. " >",
            description = "",
            positionX = 0,
            positionY = 0,
            positionZ = 10000,
            rotation = 0,
            theType = "",
            owners = {}
        }

        local timeNow = getTickCount() 
        local endTime = timeNow + 50
        local successfullyCreated = false
        local index = 0
        local timestamp = getRealTime().timestamp
        repeat
            index = index + 1
            local key = timestamp .. ":" .. index
            if not turretList:getData(key) then
                successfullyCreated = true
                turretData.id = key
                turretList:setData(key, turretData)
                break
            end
        until getTickCount() > endTime

        if successfullyCreated then
            turretDataBase:update("list",  turretList:getAllData())

            callClient(getTurretListSubscribersWithoutRequester(client), "updateTurretList", true, false, turretList:getAllData(getTurretListItemName))

            createTurretBasedOnTurretData (turretData)

            return true, "The turret has been successfully added.", turretList:getAllData(getTurretListItemName)
        end
        return false, "Can't add turret, reason unknown"
    else
        return false, "You do not have permission to add a new turret."
    end
    return false, "Something went wrong..."
end
addToWhitelist(addTurret)


function createTurretBasedOnTurretData (turretData)
    turrets:destroyBy_ID(turretData.id)

    turrets:create("anti-air", tonumber(turretData.positionX) or 0, tonumber(turretData.positionY) or 0, tonumber(turretData.positionZ) or 0, 
        {
            {
                key = "id",
                value = turretData.id
            },
            {  
                key = "rotation",
                value = turretData.rotation
            },
            {
                key = "owners",
                value = turretData.owners
            }
        }    
    )
end

function deleteTurret (id)
    if canPlayerModifyTurrets (client) then
        local turretData = turretList:getData(id)
        if turretData then
            local editor = getTurretEditor (id) 
            
            if not editor or editor == client then
                local _, dataSourceRemovalState = turretList:removeData(id)

                if not dataSourceRemovalState then
                    return false, "Couldn't delete turret from data source."
                end
                
                turrets:destroyBy_ID(id)

                local dataBaseRemovalState, reason = turretDataBase:update("list",  turretList:getAllData()) 
                if not dataBaseRemovalState then
                    return false, "Fail reason: " .. tostring(reason)
                end

                return true, "The turret has been successfully deleted from data source."
            elseif editor then
                return false, "Turret is being edited by " .. getPlayerName(editor)
            else
                return false, "Something went wrong..."
            end
        else
            return false, "Can't find turret"
        end
    else
        return false, "You do not have permission to delete a turret."
    end
    return false, "Something went wrong..."
end
addToWhitelist(deleteTurret)

function requestTurretData (id)
    if canPlayerModifyTurrets (client) then
        removePlayerFromEditingAnyTurret(client)
        local turretData = turretList:getData(id)
        if turretData then
            local editor = getTurretEditor (id)
            if not editor or editor == client then
                setPlayerEditingTurret (client, id)
                return true, false, turretData
            elseif editor then
                return false, "Turret is being edited by " .. getPlayerName(editor)
            else
                return false, "Something went wrong..."
            end
        else
            return false, "Can't find turret"
        end
    else
        return false, "You do not have permission to receive turret data."
    end
    return false, "Something went wrong..."
end
addToWhitelist(requestTurretData)

function requestUpdateTurret (id, key, value)
    if canPlayerModifyTurrets (client) then
        local turretData = turretList:getData(id)
        if turretData then
            turretData[key] = value
            if turretDataBase:update("list",  turretList:getAllData()) then
                
                createTurretBasedOnTurretData (turretData)
                
                if key == "name" then
                    callClient(getTurretListSubscribersWithoutRequester(client), "updateTurretListItemName", id, turretData.name)
                end

                return true, false, id, turretData.name
            end
            return false, "Failed to save the turret data"
        else
            return false, "Can't find turret"
        end
    else
        return false, "You do not have permission to update a turret."
    end
    return false, "Something went wrong..."
end
addToWhitelist(requestUpdateTurret)


function requestTurretList ()
    if canPlayerModifyTurrets (client) then
        return true, false, turretList:getAllData(getTurretListItemName)
    else
        return false, "You do not have permission to request the turret list."
    end
end
addToWhitelist(requestTurretList)


--[[

    Turret owners

]]

function addTurretOwner (id, accountName)
    if canPlayerModifyTurrets (client) then
        local turretData = turretList:getData(id)
        if turretData then
            local owners = turretData.owners
            if not owners[accountName] then
                owners[accountName] = true
                if turretDataBase:update("list",  turretList:getAllData()) then
                    
                    createTurretBasedOnTurretData (turretData)

                    return true, "The accountName has been successfully added.", owners
                else
                    owners[accountName] = nil
                    return false, "Failed to save the accountName in the database."
                end
            else
                return false, "This accountName already exist for this turret."
            end
        else
            return false, "Can't find turret"
        end
    else
        return false, "You do not have permission to add a turret owner."
    end
    return false, "Something went wrong..."
end

addToWhitelist(addTurretOwner)


function becomeTurretOwner (id)
    if canPlayerModifyTurrets (client) then
        local turretData = turretList:getData(id)
        if turretData then
            local account = getPlayerAccount(client)
            if not isGuestAccount(account) then
                local accountName = getAccountName(account)
                if accountName then
                    local owners = turretData.owners
                    if not owners[accountName] then
                        owners[accountName] = true
                        if turretDataBase:update("list",  turretList:getAllData()) then
                            
                            createTurretBasedOnTurretData (turretData)

                            return true, "The accountName has been successfully added.", owners
                        else
                            owners[accountName] = nil
                            return false, "Failed to save the data in the database."
                        end
                    else
                        return false, "You are already an owner of this turret."
                    end
                else
                    return false, "The function 'getAccountName' not working correctly... :o!"
                end
            else
                return false, "Please login (with the accountName you want to add)."
            end
        else
            return false, "Can't find turret."
        end
    else
        return false, "You do not have permission to add a turret owner."
    end
    return false, "Something went wrong..."
end

addToWhitelist(becomeTurretOwner)


function deleteTurretOwner(id, accountName)
    if canPlayerModifyTurrets (client) then
        local turretData = turretList:getData(id)
        if turretData then
            local owners = turretData.owners
            if owners[accountName] then
                
                owners[accountName] = nil
                if turretDataBase:update("list",  turretList:getAllData()) then
                    
                    createTurretBasedOnTurretData (turretData)

                    return true, "The accountName has been successfully removed.", owners
                else
                    return false, "Failed to save.", owners
                end
            else
                return false, "This accountName does not exist for this turret.", owners
            end
        else
            return false, "Can't find turret"
        end
    else
        return false, "You do not have permission to add a turret owner."
    end
    return false, "Something went wrong..."
end

addToWhitelist(deleteTurretOwner)




do
    --[[

        The following code is used for managing the editors for each turret. Making sure not 2 people can edit the same turret.
        It also helps with sending updates to other players that have opent the panel.

    ]]

    local editors = {}
    local turretListSubscribers = {}

    function setPlayerEditingTurret (player, id)
        if id and not isTurretEdited (id) then
            editors[id] = player
            return true
        end
        return false
    end

    function isTurretEdited (id)
        local editor = editors[id]
        if editor then
            if not (isElement(editor) and getElementType(editor) == "player") then
                editors[id] = nil
                return false
            end
            return true
        end
        return false
    end

    function getTurretEditor (id)
        local editor = editors[id]
        if editor then
            if not (isElement(editor) and getElementType(editor) == "player") then
                editors[id] = nil
                editor = nil
            end
            return editor
        end
        return false
    end

    function removePlayerFromEditingAnyTurret (player)
        for id, editor in pairs(editors) do
            if editor == player then
                editors[id] = nil
            end
        end
    end

    function addTurretListSubscriber (player)
        if not turretListSubscribers[player] then
            turretListSubscribers[player] = true
        end
    end

    
    function removeTurretListSubscriber (player)
        if turretListSubscribers[player] then
            turretListSubscribers[player] = nil
        end
    end

    function getTurretListSubscribers ()
        local subscriberList = {}
        for player, _ in pairs(turretListSubscribers) do
            subscriberList[#subscriberList + 1] = player
        end
        return subscriberList
    end

    function getTurretListSubscribersWithoutRequester (ignorePlayer)
        local subscriberList = {}
        for player, _ in pairs(turretListSubscribers) do
            if ignorePlayer ~= player then
                subscriberList[#subscriberList + 1] = player
            end
        end
        return subscriberList
    end

    addEventHandler("onPlayerQuit", root, 
    function () 
        removePlayerFromEditingAnyTurret (source)
        removeTurretListSubscriber (source)
    end)

    function unselectTurretPanelItem()
        removePlayerFromEditingAnyTurret (client)
        removeTurretListSubscriber (client)
    end
    addToWhitelist(unselectTurretPanelItem)
end