local S = minetest.get_translator("gems_battle")
minetest.register_entity("gems_battle:great_gem",{
    initial_properties = {
        visual = "mesh",
        physical = true,
        mesh = "greatgem_skeleton.b3d",
        hp_max = 32,

        visual_size = vector.new(5,5,5),
        -- backface_culling = false,
        collisionbox = {-0.25, -1, -0.25, 0.25, 1, 0.25},
    },
    get_staticdata = function(self)
        return minetest.write_json({
            team_name = self._team_name,
            teamID = self._teamID ,
            match_id = self._match_id
        })
    end,
    on_activate = function(self, staticdata, dtime_s)
        local pos = self.object:get_pos()
        if staticdata ~= "" and staticdata ~= nil then
            local data = minetest.parse_json(staticdata) or {}
            -- self._mod = data.mod
            self._team_name = data.team_name
            self._teamID = data.teamID
            self._match_id = data.match_id
            self.object:set_hp(32)
            self.object:set_properties({
                nametag = minetest.colorize(gems_battle.get_color_code(data.team_name),S("@1 Gem",gems_battle.get_capname(data.team_name)))
            })
        end

        local arena = arena_lib.get_arena_by_pos(pos, "gems_battle")
        if (not (arena)) or self._match_id ~= arena.matchID then 
            self.object:remove()
            return
        end 

        local has_children = false
        local children = self.object:get_children()
        if not children[6] then
            for i=1,6 do
                local name = "gems_battle:great_gem_side"
                local offset = vector.new(0,0,0)
                local rot = vector.new(0,0,0)

                if i == 5 then name = "gems_battle:great_gem_top" end 
                if i == 6 then name = "gems_battle:great_gem_bottom" end 
                if i == 1 then
                    offset = vector.new(-0.5,0,0)
                    rot = vector.new(0,90,0)
                end
                if i == 2 then
                    offset = vector.new(0.5,0,0)
                    rot = vector.new(0,-90,0)
                end
                if i == 3 then
                    offset = vector.new(0,0,-0.5)
                    rot = vector.new(0,0,0)
                end
                if i == 4 then
                    offset = vector.new(0,0,0.5)
                    rot = vector.new(0,180,0)
                end
                if i == 5 then
                    offset = vector.new(0,2,0)
                    rot = vector.new(0,0,0)
                end
                if i == 6 then
                    offset = vector.new(0,-2,0)
                    rot = vector.new(0,0,0)
                end
                local face = minetest.add_entity(self.object:get_pos(), name)
                face:set_attach(self.object, "", offset, rot)
            end
        end

        

        self:_update_textures()
        self.object:set_armor_groups({immortal=1})

        

    end,
    _punch_time = 0,
    _check_elim = 0,
    on_step = function (self,dtime)
        self._punch_time = self._punch_time + dtime
        self._check_elim = self._check_elim + 1
        if self._check_elim > 1 then
            self._check_elim = 0
            local arena = arena_lib.get_arena_by_pos(self.object:get_pos(), "gems_battle")
            if arena and arena.in_game and self._teamID and arena.teams[self._teamID] then 
                if arena.teams[self._teamID].team_eliminated then
                    arena.teams[self._teamID].gem_hp = 0
                    self.object:set_hp(0)
                end
            end
        end
    end,
    on_punch = function(self, puncher, time_from_last_punch, toolcaps, dir, damage)
        if self._punch_time < .5 then
            return
        end
        self._punch_time = 0
        local p_name = puncher:get_player_name()
        if not p_name then return end
        if not arena_lib.is_player_playing(p_name, "gems_battle") then return end
        local arena = arena_lib.get_arena_by_player(p_name)
        if not arena.in_game then return end
        -- you can't hurt your own team's gem
        if arena.teams[arena.players[p_name].teamID].name == self._team_name then return end
        
        -- checks done!
        local inv = puncher:get_inventory()
        local witem = puncher:get_wielded_item()
        local wlist = puncher:get_wield_list()
        local windex = puncher:get_wield_index()

        local dg = toolcaps.damage_groups
        local dodamage = false
        local invtime = 2
        local adddamage = 1
    
        if dg.gem then 
            dodamage = true
            invtime = dg.gem
            if dg[self._team_name] then
                invtime = dg[self._team_name]
            end
            if dg.gem_pick and dg[self._team_name] then
                adddamage = 2
            end
        end

        -- the gem damage group is 2 / rating seconds until next punch
        -- if dodamage and (time_from_last_punch > 2/invtime) and self.object:get_hp() > 0 then
        if dodamage and self.object:get_hp() > 0 then
            self.object:set_hp(self.object:get_hp()-adddamage)
            -- todo: set the game's internal variables
            local hp = arena.teams[self._teamID].gem_hp - adddamage
            if hp < 0 then hp = 0 end
            arena.teams[self._teamID].gem_hp = hp
            arena.teams[self._teamID].under_attack = 3
            
            for _,p_name in pairs(arena_lib.get_players_in_team(arena, self._teamID)) do
                local numbercolor = tonumber("0x"..string.sub(gems_battle.get_color_code(arena.teams[self._teamID].name),2,-1))
                arena_lib.HUD_send_msg("broadcast", p_name, S("Great Gem under attack!"), 2, nil, numbercolor)
            end
            self:_update_textures()
        end
    end,
    on_death = function(self)
        local children = self.object:get_children()
        for _,child in pairs(children) do
            child = child:get_luaentity()
            child:remove()
        end
    end,
    _mod = nil,
    _team_name = "none",
    _teamID = -1,
    _match_id = -1,
    _update_textures = function(self)
        
        local children = self.object:get_children()
        if children == nil then return end
        for _,child in pairs(children) do
            child = child:get_luaentity()
            child:_update_textures()
        end
        local pos = self.object:get_pos()
        local height = pos.y - 1 + (self.object:get_hp()/16)
        local center = vector.new(pos.x,height,pos.z)
        minetest.add_particlespawner({

            amount = 20,          
            time = 1,          
            collisiondetection = true,
            collision_removal = false,
            object_collision = false,
            texture = "gems_particle_"..self._team_name..".png^[opacity:150",
            glow = 3,


            -- legacy defs
            minpos = vector.add(center,vector.new(-.6,0,-.6)),
            maxpos = vector.add(center,vector.new(.6,0,.6)),
            minvel = vector.new(-1,0,-1),
            maxvel = vector.new(1,0,1),
            minacc = vector.new(0,-9.8,0),
            maxacc = vector.new(0,-9.8,0),
            minexptime = 2,
            maxexptime = 2,
            minsize = 1,
            maxsize = 1,

            --modern defs
            texture = {
                name = "gems_particle_"..self._team_name..".png",
                alpha_tween = {
                    0.0, 1.0,
                    style = "pulse",
                    reps = 3,
                },
                scale_tween = {
                    0.5, 1.0,
                    style = "pulse",
                    reps = 3,
                },
            },
            drag = 2,
            bounce = .5,
            vel = 0,
            attract = {
                strength = -1.5,
                kind = "plane",
                origin = center,
                direction = vector.new(0,1,0),
                radius = {min = 0.5, max = 1, bias = 1},
            },
        })
    end

            
})

minetest.register_entity("gems_battle:great_gem_side",{
    initial_properties = {
        visual = "mesh",
        physical = false,
        pointable = false,
        mesh = "greatgem_side.b3d",
        hp_max = 32,
        textures = {"gems_greatgem_side.png^[opacity:127"},
        -- visual_size = vector.new(10,10,10),
        backface_culling = false,
        use_texture_alpha = true,
        glow = 3,
    },
    on_step = function (self) if not(self.object:get_attach()) then self.object:remove() end end,
    _update_textures = function(self)
        local parent = self.object:get_attach()
        if not parent then 
            minetest.log("Parent not found!")
            self.object:remove()
        end
        local parentent = parent:get_luaentity()
        local tex = {"gems_greatgem_side.png^[opacity:127"}
        
        if parentent._team_name then
            local color_code = gems_battle.get_color_code(parentent._team_name) or "#e6482e"
            local percent = (parentent.object:get_hp()/32)*100
            tex[1] = tex[1] .. string.format("^[lowpart:%s:gems_greatgem_side.png\\^[opacity\\:127\\^[colorize\\:%s\\:170",percent,color_code)
            self.object:set_properties({textures = tex})
        end
    end            
})

minetest.register_entity("gems_battle:great_gem_top",{
    initial_properties = {
        visual = "mesh",
        physical = false,
        pointable = false,
        mesh = "greatgem_top.b3d",
        hp_max = 32,
        textures = {"gems_greatgem_top.png^[opacity:127"},
        -- visual_size = vector.new(10,10,10),
        use_texture_alpha = true,
        backface_culling = false,
        glow = 3,

    },
    on_step = function (self) if not(self.object:get_attach()) then self.object:remove() end end,
    _update_textures = function(self)
        local parent = self.object:get_attach()
        if not parent then 
            minetest.log("Parent not found!")
            self.object:remove()
        end
        local parentent = parent:get_luaentity()
        
        local tex = {"gems_greatgem_top.png^[opacity:127"}
        if parentent._team_name then
            local color_code = gems_battle.get_color_code(parentent._team_name) or "#e6482e"
            local percent = parentent.object:get_hp()/32*100
            if parentent.object:get_hp() == 32 then
                tex[1] = tex[1] .. string.format("^[colorize:%s:170",color_code)
            end
            self.object:set_properties({textures = tex})
        end
    end            
})


minetest.register_entity("gems_battle:great_gem_bottom",{
    initial_properties = {
        visual = "mesh",
        physical = false,
        pointable = false,
        mesh = "greatgem_top.b3d",
        hp_max = 32,
        textures = {"gems_greatgem_top.png^[opacity:127"},
        -- visual_size = vector.new(10,10,10),
        use_texture_alpha = true,
        backface_culling = false,
        glow = 3,

    },
    on_step = function (self) if not(self.object:get_attach()) then self.object:remove() end end,
    _update_textures = function(self)
        local parent = self.object:get_attach()
        if not parent then 
            minetest.log("Parent not found!")
            self.object:remove()
        end
        local parentent = parent:get_luaentity()
        
        local tex = {"gems_greatgem_top.png^[opacity:127"}
        if parentent._team_name then
            local color_code = gems_battle.get_color_code(parentent._team_name) or "#e6482e"
            local percent = parentent.object:get_hp()/32*100
            if parentent.object:get_hp() > 0 then
                tex[1] = tex[1] .. string.format("^[colorize:%s:170",color_code)
            end
        
            self.object:set_properties({textures = tex})
        end
    end            
})





-- shopkeepers

function gems_battle.register_shopkeeper(team)
    minetest.register_entity("gems_battle:shopkeeper_"..team,{
        initial_properties = {
            visual = "mesh",
            physical = true,
            mesh = "3d_armor_character.b3d",
            hp_max = 32,
            textures = {
                "shopkeeper_"..team..".png",
                "3d_armor_trans.png",
                "3d_armor_trans.png",
            },
            -- visual_size = vector.new(5,5,5),
            -- backface_culling = false,
            collisionbox = {-0.3, 0.0, -0.3, 0.3, 1.7, 0.3},
            nametag = minetest.colorize(gems_battle.get_color_code(team), S("@1 Shop",gems_battle.get_capname(team))),
        },
        
        on_punch = function(self, puncher, time_from_last_punch, toolcaps, dir, damage)
            return 0
        end,
        _timer = 0,
        on_step = function(self,dtime)
            local aid, arena = arena_lib.get_arena_by_matchID(self._match_id)
            if (not (arena)) or self._match_id == nil or self._match_id ~= arena.matchID then
                self.object:remove()
                return
            end
            self._timer = self._timer + dtime
            if self._timer > .2 then 
                local pos = self.object:get_pos()
                self._timer = 0
                local objs = minetest.get_objects_inside_radius(pos,4)
                local playerstor
                for _,obj in pairs(objs) do 
                    if obj:is_player() then
                        local dist = vector.distance(pos,obj:get_pos())
                        if not(playerstor) then 
                            playerstor = {obj,dist}
                        elseif dist < playerstor[2] then
                            playerstor = {obj,dist}
                        end
                    end
                end
                if playerstor then 
                    local player = playerstor[1]
                    local direction = vector.direction(pos, player:get_pos())
                    local rot = vector.dir_to_rotation(direction)
                    self.object:set_yaw(rot.y)
                end
            end

        end,

        on_rightclick = function(self,player)
            gems_battle.show_shop_formspec(team, player)
        end,
        _team_name = "none",
        _first = "",
        _match_id = 0,
        get_staticdata = function(self)
            return minetest.write_json({
                _first = self._first,
                match_id = self._match_id
            })
        end,
        on_activate = function(self, staticdata, dtime_s)
            if staticdata ~= "" and staticdata ~= nil then
                local data = minetest.parse_json(staticdata) or {}
                self._match_id = data.match_id

                if data._first then
                    self._first = data._first
                end
            end
            if self._first ~= "false" then
                self._first = "false"
                self.object:set_velocity(vector.new(0,-1,0))
            end
        end,
    })
end

for _,gem_name in pairs(gems_battle.team_names) do
    gems_battle.register_shopkeeper(gem_name)
end


minetest.register_entity("gems_battle:player_keeper",{
    initial_properties = {
        visual = "sprite",
        physical = false,
        hp_max = 32,
        textures = {"blank.png"},
        collisionbox = {-.1,-.1,-.1,.1,.1,.1},
    },
    
    _timer = 0,
    on_step = function(self,dtime)

        self._timer = self._timer + dtime
        if self._timer >= 10 then
            local children = self.object:get_children()
            if #children >= 1 then 
                children[1]:set_detach()
            end
            self.object:remove()
        end
    end,
})


minetest.register_entity("gems_battle:gem_nametag",{
    initial_properties = {
        visual = "upright_sprite",
        physical = false,
        pointable = false,
        hp_max = 32,
        textures = {"item_ruby.png"},
        visual_size = {x=.4,y=.4},
    },
    
    _timer = 0,
    on_step = function(self,dtime)
        self._timer = self._timer + dtime
        if self._timer >= .1 then
            local att = self.object:get_attach()
            if not(att) then
                self.object:remove()
            else
                local p_name = att:get_player_name()
                if p_name then 
                    if not(arena_lib.is_player_playing(p_name,"gems_battle")) then 
                        self.object:remove()
                    end
                end
            end            
        end
    end,
})


-- marker for editor

minetest.register_entity("gems_battle:pos_ent",{
    initial_properties = {
        physical = false,
        use_texture_alpha = true,
        collisionbox = {-0.01, -0.01, -0.01, 0.01, 0.01, 0.01},
        visual = "cube",
        textures = {"blank.png","blank.png","blank.png","blank.png","blank.png","blank.png"},
        visual_size = {x = 1.3, y = 1.3, z = 1.3},
        static_save = false,
    },
    on_activate = function(self, staticdata, dtime_s)
        if staticdata ~= "" and staticdata ~= nil then
            local data = minetest.parse_json(staticdata) or {}
            if data._arena then self._arena = data._arena end
            if data._property then self._property = data._property end
            if data._textures then self._textures = data._textures end
        end
    end,
    on_step = function(self, dtime, moveresult)
        
        self._timer = self._timer + dtime

        if self._timer > .1 then

            if self._arena == "" then 
                self.object:remove()
                return
            end

            if not arena_lib.get_arena_by_name('gems_battle', self._arena ) then 
                self.object:remove()
                return
            end

            local arena_id, arena = arena_lib.get_arena_by_name('gems_battle', self._arena )

            if arena.enabled == true then
                self.object:remove()
                return
            end

            if self._property then
                local pos_type = self._property
                local textures = self._textures
                self.object:set_properties({textures = {textures,textures,textures,textures,textures,textures,}})
                local objpos = vector.floor(self.object:get_pos())
                local arpos = arena[pos_type]
                if not(objpos.x == arpos.x and objpos.y == arpos.y and objpos.z == arpos.z)  then
                    self.object:remove()
                    return
                end
            end
            
        end
        
    end,

    _arena = "",
    _property = "",
    _timer = 0.0,

})
