skins.meta = {}

local skin_class = {}
skin_class.__index = skin_class
skins.skin_class = skin_class
-----------------------
-- Class methods
-----------------------
-- constructor
function skins.new(key, object)
	assert(key, 'Unique skins key required, like "character_1"')
	local self = object or {}
	setmetatable(self, skin_class)
	self.__index = skin_class

	self._key = key
	self._sort_id = 0
	skins.meta[key] = self
	return self
end

-- getter
function skins.get(key)
	return skins.meta[key]
end

-- Skin methods
-- In this implementation it is just access to attrubutes wrapped
-- but this way allow to redefine the functionality for more complex skins provider
function skin_class:get_key()
	return self._key
end

function skin_class:set_meta(key, value)
	self[key] = value
end

function skin_class:get_meta(key)
	return self[key]
end

function skin_class:get_meta_string(key)
	return tostring(self:get_meta(key) or "")
end

function skin_class:set_texture(value)
	self._texture = value
end

function skin_class:get_texture()
	return self._texture
end

function skin_class:set_preview(value)
	self._preview = value
end

function skin_class:get_preview()
	return self._preview or "player.png"
end

function skin_class:apply_skin_to_player(player)

	local function concat_texture(base, ext)
		if base == "blank.png" then
			return ext
		elseif ext == "blank.png" then
			return base
		else
			return	base .. "^" .. ext
		end
	end

	local playername = player:get_player_name()
	local ver = self:get_meta("format") or "1.0"
	default.player_set_model(player, "skinsdb_3d_armor_character.b3d")

	local v10_texture = "blank.png"
	local v18_texture = "blank.png"
	local armor_texture = "blank.png"
	local wielditem_texture = "blank.png"

	if ver == "1.8" then
		v18_texture = self:get_texture()
	else
		v10_texture = self:get_texture()
	end

	-- Support for clothing
	if skins.clothing_loaded and clothing.player_textures[playername] then
		local cape = clothing.player_textures[playername].cape
		local layers = {}
		for k, v in pairs(clothing.player_textures[playername]) do
			if k ~= "skin" and k ~= "cape" then
				table.insert(layers, v)
			end
		end
		local overlay = table.concat(layers, "^")
		v10_texture = concat_texture(v10_texture, cape)
		v18_texture = concat_texture(v18_texture, overlay)
	end

	-- Support for armor
	if skins.armor_loaded then
		local armor_textures = armor.textures[playername]
		if armor_textures then
			armor_texture = concat_texture(armor_texture, armor_textures.armor)
			wielditem_texture = concat_texture(wielditem_texture, armor_textures.wielditem)
		end
	end

	default.player_set_textures(player, {
			v10_texture,
			v18_texture,
			armor_texture,
			wielditem_texture,
		})

	player:set_properties({
		visual_size = {
			x = self:get_meta("visual_size_x") or 1,
			y = self:get_meta("visual_size_y") or 1
		}
	})
end

function skin_class:set_skin(player)
	-- The set_skin is used on skins selection
	-- This means the method could be redefined to start an furmslec
	-- See character_creator for example
end

function skin_class:is_applicable_for_player(playername)
	local assigned_player = self:get_meta("playername")
	return assigned_player == nil or assigned_player == true or
			(assigned_player:lower() == playername:lower())
end