-- модуль для отрисовки аватаров игроков
avatar_widget = {}

avatar_widget._count = 0

__inherite(avatar_widget, null_lua_widget_handler())

function avatar_widget.__CreateInstance()
    return "avatar_widget"
end

avatar_widget._current_clip = nil  -- текущий клип аватара

avatar_widget._new_clip = nil      -- клип на который заменяется текущий  
avatar_widget._change_count = 0    -- время оставшееся до полной замены

avatar_widget._change_time = 220  -- время смены состояния

avatar_widget._draw_mode_bar = false -- рисовать ли график настроения

avatar_widget._changes = {
	-- delta - изменение настроения
	-- limit - максимальное изменение этим событием
	-- happy - время, которое игрок будет радовать при данном событии(если не указано то не будет радоваться)
	
	town_no_res =    {delta = -10, limit = -50},  -- нажатие на кнопку купить если мало ресурсов
	town_sell =      {delta = -45, limit = -60},  -- продажа здания 
	town_buy =       {delta = 100, limit = 70},  -- покупка задния
	
	no_moves_classic = {delta = -70, limit = -50}, 	-- ситуации «нет ходов» в режиме classic (во время эффекта сброса поля) 4 -состояние аватара моментально изменяется на грустное
	no_moves_endless = {delta = -90, limit = -70},	-- ситуации «нет ходов» и endless (во время эффекта сброса поля) 9 -состояние аватара моментально изменяется на грустное
	
	no_moves_puzzle =  {delta = -60, limit = -50},   -- ситуации нет ходов в Puzzle (сменяется на обычное после нажатия нажатия на хинт, undo или сброс) 6 состояние аватара моментально изменяется на грустное
	no_moves_puzzle_turn_off = {delta = 90, limit = 40},   -- после нажатия нажатия на хинт, undo или сброс, при ситуации нет ходов в режиме puzzle
	
	no_moves_puzzle =  {delta = -70, limit = -50},   -- ситуации нет ходов в Puzzle (сменяется на обычное после нажатия нажатия на хинт, undo или сброс) 6 состояние аватара моментально изменяется на грустное
	no_moves_puzzle_turn_off = {delta = 80, limit = 20},   -- после нажатия нажатия на хинт, undo или сброс, при ситуации нет ходов в режиме puzzle
	finish_level =     {delta = 150, limit = 90}, -- завершении уровня в режимах classic и puzzle (в том числе и во время отображения статистики) 5 состояние аватара моментально изменяется на радостное
	endless_finish_session = {delta = 70, limit = 60}, -- завершение сессии в режиме endless (во время эффекта завершения сессии) 5 состояние аватара моментально изменяется на радостное
	on_score_frenzy =  {delta = 100, limit = 100}, -- включение супер-режима, состояние аватара моментально изменяется на радостное
	on_add_time =      {delta = 20, limit = 70}, -- включение супер-режима, состояние аватара моментально изменяется на радостное
	
	combo_good =     {delta = 5, limit = 60, happy = 10}, --  комбо, состояние аватара моментально изменяется на радостное
	combo_great =    {delta = 7, limit = 65, happy = 10}, -- комбо,  состояние аватара моментально изменяется на радостное
	combo_incr =     {delta = 9, limit = 70, happy = 15}, -- комбо, состояние аватара моментально изменяется на радостное
	bonus_destroy =  {delta = 10, limit = 70, happy = 15}, -- игрок бонус разрушил на матче
	row_destroy =    {delta = 5, limit = 50}, -- игрок разрушил ряд
	totem_use_1 =    {delta = 10, limit = 60, happy = 20}, -- применение тотема (два матча подряд)
	totem_use_2 =    {delta = 12, limit = 60, happy = 5}, -- применение тотема многократное (три матча подряд)
	no_moves_delay = {delta = -70, limit = -60}, -- игрок долго не делает ходы
	bad_moves =      {delta = -40, limit = -70}, -- игрок делает неправильные ходы
	bad_moves_turn_off = {delta = 120, limit = 30, happy  = 1 }, -- игрок верный ход после большойго числа неверных
	time_limit =     {delta = -200, limit = -60 }, -- время подходит к концу
	
	test_down =      {delta = -10, limit = -100},  -- тестовые состояния для читов
	test_up =        {delta = 10, limit = -100},   
}

avatar_widget._mood = 0 -- состояние

avatar_widget._happy_min_mood = -30 --- минимальный уровень настроения при котором возможно счастье

avatar_widget._max_mood = 100 -- состояние
avatar_widget._min_mood = -100 -- состояние

avatar_widget._bad_mood_start = -40 --начало плохого состояния
avatar_widget._good_mood_start = 40 -- начало хорошего состояния 

avatar_widget._bad_mood_fading = 3 -- скорость затухания хорошего состояния
avatar_widget._good_mood_fading = 3 -- начало хорошего состояния 

avatar_widget._test_bar_offset = sf.misc.FloatVector(-50, -50) -- смещение 

avatar_widget._test_bar_width = 120 -- шрина тестовой шкалы настроения

avatar_widget._happy_time = 0 -- время счастья (кратковременная улыбка)
avatar_widget._max_happy_time = 2400 -- максималное время счастья
avatar_widget._min_happy_time = 1100 -- максималное время счастья

-- id клипов для лиц
avatar_widget._clip_ids = {
	woman = {
		neutral = "avatar_woman_neutral",
		happy   = "avatar_woman_happy",
		sad     = "avatar_woman_sad"
	},
	
	man = {
		neutral = "avatar_man_neutral",
		happy   = "avatar_man_happy",
		sad     = "avatar_man_sad"
	}
}

-- добавить кратковременное счастье игроку
function avatar_widget.AddHappy(_time)
	if avatar_widget._mood > avatar_widget._happy_min_mood then
	
		if avatar_widget._happy_time + _time <= avatar_widget._max_happy_time then
			avatar_widget._happy_time = avatar_widget._happy_time + _time
		else
			avatar_widget._happy_time = avatar_widget._max_happy_time
		end
		if avatar_widget._happy_time < avatar_widget._min_happy_time then
			avatar_widget._happy_time = avatar_widget._min_happy_time
		end
	end
	avatar_widget._CheckMoodState()
end

-- изменить настроение
function avatar_widget.ChangeMood(_id)
	local change_info = avatar_widget._changes[_id] 
	-- проверка чт отакое влияние на настроение есть
	if not change_info then
		__message("unknow mod change id "..tostring(_id))
	else
		-- если нужно сделать игрока счастливым
		if change_info.happy then
			avatar_widget.AddHappy(change_info.happy)
		end
		
		-- смотрим как должно изменитсья настроение
		local delta = change_info.delta
		if delta > 0 then
			-- должно увеличиться
			if avatar_widget._mood + delta < change_info.limit then
				avatar_widget._mood = avatar_widget._mood + delta
			elseif avatar_widget._mood < change_info.limit then
				avatar_widget._mood = change_info.limit
			end
			if avatar_widget._mood > avatar_widget._good_mood_start then
				avatar_widget.ChangeSate("happy")	
			end
		
		else
			-- должно уменьшиться
			if avatar_widget._mood + delta > change_info.limit then
				avatar_widget._mood = avatar_widget._mood + delta
			elseif avatar_widget._mood > change_info.limit then
				avatar_widget._mood = change_info.limit
			end
			if avatar_widget._mood < avatar_widget._bad_mood_start then
				avatar_widget.ChangeSate("sad")	
			end
		end
	end
end

-- сменить состояние аватара
function avatar_widget.ChangeSate(_id)
	-- если игрок должне быть счастлив, то состаяние меняется на счастливое
	if avatar_widget._happy_time > 0 then
		_id = "happy"
	end

	-- получаем клип, на который хотим сменить текущий
	local target_clip  = avatar_widget._clip_list[_id]
	-- если щас идет смена состояния
	if avatar_widget._new_clip then
		
		if avatar_widget._new_clip == target_clip then
			-- если уже идет смена состояния на тот же клип то выходим
			return
		elseif avatar_widget._current_clip == target_clip then
			-- если заменяется то состояние на которое мы хотим сменить авватар
			-- то мы обращаем изменние в спять
			avatar_widget._current_clip = avatar_widget._new_clip
			avatar_widget._new_clip = target_clip
			avatar_widget._change_count = avatar_widget._change_time - avatar_widget._change_count
			return 
		end
	else
		-- если текущее состояние уже установлено
		if avatar_widget._current_clip == target_clip then
			-- выходим
			return
		end
	end
	-- если дошли до этого момоента то просто инициируем смену состояния
	avatar_widget._change_count = avatar_widget._change_time
	avatar_widget._new_clip = target_clip
end

function avatar_widget.Load(_this, _info, _templates)
	avatar_widget._timer = sf.core.CTimerWrapper(sf.core.g_Application.GetTimeManager().GetTimer("game_timer").AttachTimer(""))
	return true
end

-- обновление состояния в зависимости от настроения
function avatar_widget._CheckMoodState()
	if avatar_widget._mood < avatar_widget._bad_mood_start then
		avatar_widget.ChangeSate("sad")
	elseif avatar_widget._mood > avatar_widget._good_mood_start then
		avatar_widget.ChangeSate("happy")
	else
		avatar_widget.ChangeSate("neutral")	
	end
end

-- инициализация аватара в начале
function avatar_widget.InitAvatar(_is_female, _do_not_drop_mood)
	local clips_id = "man"
	if _is_female then
		clips_id = "woman"
	end
	avatar_widget._clip_list  = {}
	for id, clip_id in pairs(avatar_widget._clip_ids[clips_id]) do
		local new_clip = sf.misc.anim.CClip()
		new_clip.Load(clip_id, true)
		avatar_widget._clip_list[id] = new_clip
	end
	-- если нужно сбрасываем состояние в нейтральное
	if not _do_not_drop_mood then
		avatar_widget._mood = 0
		avatar_widget._current_clip = avatar_widget._clip_list["neutral"]
	else 
		avatar_widget._CheckMoodState()
	end
end

function avatar_widget.DoUpdate(_this)

	avatar_widget._current_clip.Update()	
	local frame_delta = avatar_widget._timer.Get().GetFrameDelta()
	-- обновлем время счастья
	if avatar_widget._happy_time > 0 then
		avatar_widget._happy_time = avatar_widget._happy_time - frame_delta
		if avatar_widget._happy_time <= 0 then
			avatar_widget._happy_time = 0
			avatar_widget._CheckMoodState()
		end
	end
	
	-- обновляем отрисовку если нужно
	if avatar_widget._change_count > 0 then
		
		avatar_widget._change_count = avatar_widget._change_count - frame_delta
		avatar_widget._new_clip_alpha_koef = 1 - (avatar_widget._change_count/avatar_widget._change_time)
		if avatar_widget._change_count <= 0 then
			avatar_widget._current_clip = avatar_widget._new_clip
			avatar_widget._new_clip = nil
		end
	end
	
	-- обновляем смену настроения
	local mood = avatar_widget._mood
	if math.abs(mood) > 0.1 then
		if mood > 0 then
		   mood = mood - (avatar_widget._good_mood_fading * frame_delta)/1000
		   if mood < avatar_widget._good_mood_start then
				avatar_widget.ChangeSate("neutral")	
		   end
		else
		   mood = mood + (avatar_widget._bad_mood_fading * frame_delta)/1000
		   if mood > avatar_widget._bad_mood_start then
				avatar_widget.ChangeSate("neutral")	
		   end
		end
		avatar_widget._mood = mood
	end
	
	return false
end

-- тестовая отрисовка полосочки на шкале настроения
function avatar_widget.DrawMood( _renderer, _mood, _color)
	
	local max_len = math.abs(avatar_widget._max_mood - avatar_widget._min_mood)
	local _mood_len = math.abs(_mood - avatar_widget._min_mood)
	
	local _dist = (_mood_len * avatar_widget._test_bar_width)/max_len
	
	avatar_widget.DrawBar( _renderer, _dist, _color)
end

function avatar_widget.DrawBar( _renderer, _dist, _color)
	_renderer.RenderLine(avatar_widget._test_bar_offset + sf.misc.FloatVector(_dist, -10),avatar_widget._test_bar_offset  + sf.misc.FloatVector(_dist,10), _color)
end

function avatar_widget.DoDraw(_this, _renderer)

	avatar_widget._current_clip.Draw(_renderer)
	
	if avatar_widget._new_clip and avatar_widget._new_clip_alpha_koef then
		local color = sf.graphics.Color(_renderer.GetColor())
		color.Alpha = color.Alpha * avatar_widget._new_clip_alpha_koef
		_renderer.SetColor(color)
		avatar_widget._new_clip.Draw(_renderer)
	end
	if avatar_widget._draw_mode_bar then
		if sf.core.g_Application.GetDebugLevel() >= sf.core.g_Application.DebugCheats then
			avatar_widget.DrawBar(_renderer, 0, 0xffffffff)
			avatar_widget.DrawBar(_renderer, avatar_widget._test_bar_width, 0xffffffff)
			
			avatar_widget.DrawMood( _renderer, avatar_widget._bad_mood_start, 0xff8888ff)
			avatar_widget.DrawMood( _renderer, avatar_widget._good_mood_start, 0xff8888ff)
			avatar_widget.DrawMood( _renderer, 0, 0xffff8888)
			
			avatar_widget.DrawMood( _renderer, avatar_widget._mood, 0xffff00ff)
		end
	end
    return false
end

function avatar_widget.OnMouseMove(_this, _pos, _state, _broadcast)
    return false
end

function avatar_widget.OnMouseUp(_this, _pos, _button, _state, _broadcast)
    return false
end

function avatar_widget.OnMouseDown(_this, _pos, _button, _state, _broadcast)
    return false
end

function avatar_widget.OnDoubleClick(_this, _pos, _state, _broadcast)
    return true
end
