-- модлуь реализующий зеленый тотем
totems_widget = totems_widget or {}
totems_widget._totem_effect_create_functions = totems_widget._totem_effect_create_functions or {}
totems_widget._totem_load_options_functions = totems_widget._totem_load_options_functions or {}

--настройки тотема
totems_widget._green_totem_options = {
	lightning_fly_time = 550, -- время полета молнии
	lightning_start_pos = sf.misc.FloatVector(100, 600), -- начальная позиция молнии
	gem_fly_time = 750, -- время полета гема на поле
	gem_start_pos = sf.misc.FloatVector(100, 600), -- позиция откуда летит гем
	hit_scale = sf.misc.FloatVector(2.1, 2.4), -- растяжение спиарли
	hit_speed = 1200, -- скорость спирали
	hit_start_part = 0.3, -- начальная позиция спирали в текстуре молнии
	hit_delta = 200, -- время отсавания хвоста
	after_add_delay = 200 -- задержка полсе добавления гема тотеомом
}

-- функция загрузки специфичных для тотема параметров
totems_widget._totem_load_options_functions[s11.CFieldCap.CapTypeGreen] = function (_totems_info)
	local options = totems_widget._green_totem_options
	options.lightning_fly_time = tonumber(_totems_info.GetValue("lightning_fly_time").c_str()) or 0
	options.lightning_start_pos = totems_widget.GetAbsOffset(StringToFloatVector(_totems_info.GetValue("lightning_start_pos").c_str()))
	options.gem_fly_time = tonumber(_totems_info.GetValue("gem_fly_time").c_str()) or 0
	options.gem_start_pos = totems_widget.GetAbsOffset(StringToFloatVector(_totems_info.GetValue("gem_start_pos").c_str()))
	options.after_add_delay = tonumber(_totems_info.GetValue("after_add_delay").c_str()) or 0
end

-- добавляем эффект удара по камню зеленым тотемом
-- _cell - ячейка по которой будет нанесен удар
-- _start_pos - начальная позиция ударяющего эффеекта
local HitCellEffect = function(_cell, _start_pos)
	local options = totems_widget._green_totem_options
	
	
    local new_child_effect = 
    {
        Init = function(_self, _cell, _start_pos)
			_self._cell = _cell
			_self._cell.AddLock()
			_self._start_pos = _start_pos
			_self._end_pos = game_helpers.GetFieldPos() + _cell.GetCapPos(true)
			
			_self._wave_image = s11.effects.CImageWave(_self._start_pos, _self._end_pos, options.hit_scale, options.hit_start_part)
			_self._max_part = _self._wave_image.GetMaxStep()
			
			
			
            _self._start_time = effects_widget.effects_timer.Get().GetTime()
            _self._total_time = CalcTimeForVector(_self._start_pos, _self._end_pos, options.hit_speed)
            _self._end_time = _self._start_time + _self._total_time
			
            _self._tail_time = _self._total_time + options.hit_delta
			_self._tail_start_koef = options.hit_delta / _self._tail_time
            _self._tail_end_time = _self._start_time + _self._tail_time
			
			_self._koef = 0
			_self._tail_koef = 0
			_self._hit = nil

			_self._particle_effect = effects_widget.visual_effects:CreateEffect("GreenTotemFly", _start_pos)  
			_self._fly_pos = _self._start_pos

        end,

        Draw = function(_self, _renderer)
			_self._wave_image.Draw(_renderer, _self._tail_koef*_self._max_part, _self._koef*_self._max_part)
        end,

        Update = function(_self, _time)
            _self._koef = (_time - _self._start_time)/_self._total_time
			if _self._koef > 1 then
				_self._koef = 1
				_self._fly_pos = _self._end_pos
			else
				_self._fly_pos = _self._wave_image.GetPosByPart(_self._koef*_self._max_part)
			end
			_self._particle_effect:SetPos(_self._fly_pos)
			
			local tail_koef = (_time - _self._start_time)/_self._tail_time
			if tail_koef > _self._tail_start_koef then
				_self._tail_koef = (_time - _self._start_time - options.hit_delta)/(_self._tail_time - options.hit_delta)
			end
			if not _self._hit and _self._koef >= 1 then
				_self._hit = true
				_self._cell.DecLock()
				game_window.game_field.BlowUpCell(_self._cell, 0, 0)
			end
            if _time > _self._tail_end_time then
                _self:InstantApply()
            end
        end,

        InstantApply = function(_self)
            if not _self._is_dead then
				if not _self._hit then
					_self._hit = true
					_self._cell.DecLock()
					game_window.game_field.BlowUpCell(_self._cell, 0, 0)
				end
				_self._particle_effect:Kill(false)
			end

            _self._is_dead = true
        end,

        IsDead = function(_self)
			return _self._is_dead
        end,
    }
	new_child_effect:Init(_cell, _start_pos)
	effects_widget.add_effect(new_child_effect)
	-- возвращаем созданый эффект, для того что бы зеленый тотем мог его мониторить
	return new_child_effect
end

-- эффект добавления гема на поле
-- _start_pos - координаты откуда прилетит гем
-- _cell - ячейка на поле в которую прилетит гем
-- _fly_time - время полета камня
-- _delay - задержка после добалвения
local AddGemOnField = function(_start_pos, _cell, _fly_time, _delay)
    local new_child_effect = 
    {
        Init = function(_self, _total_time, _start_pos, _cell, _delay)
			_self._cell = _cell
            _self._start_time = effects_widget.effects_timer.Get().GetTime()
            _self._total_time = _total_time
            _self._end_time = _self._start_time + _self._total_time
			_self._start_pos = _start_pos - effects_widget._gem_size/2
			_self._end_pos = game_helpers.GetFieldPos() + _cell.GetCapPos(true) - effects_widget._gem_size/2
			local cap = _cell.GetCap()
			_self._gem_image = effects_widget._gems_map[cap.GetType()]
			if not cap or not cap.IsColored() then
				_self._is_dead = true
				return
			end
			_self._cell.AddLock()
			_self._gem_size_half = effects_widget._gem_size / 2
			_self._particle_effect = effects_widget.visual_effects:CreateEffect("GemFlyOnField", _start_pos)      
			_self._stage = 1
			_self._delay = _delay
        end,

        Draw = function(_self, _renderer)
			if _self._fly_obj_pos ~= nil and _self._stage == 1 then
				_renderer.PushState()
				_renderer.ApplyMatrix( sf.misc.MatrixTranslation(_self._fly_obj_pos.X, _self._fly_obj_pos.Y))
				_self._gem_image.Draw(_renderer)
				_renderer.PopState()
			end
        end,

        Update = function(_self, _time)
			if _self._is_dead then
				return
			end
            local koef = (_time - _self._start_time)/_self._total_time
			if _self._stage == 1 then
				_self._fly_obj_pos = effects_widget.SimpleFlyFunction( _self._start_pos, _self._end_pos, koef)
				_self._particle_effect:SetPos(_self._fly_obj_pos + _self._gem_size_half)
				if koef >= 1 then
					--_self:InstantApply()
					game_window.game_field.AddGemToCell(_self._cell, true)
					effects_widget.visual_effects:CreateInstantEffect("GemHitToCap", _self._fly_obj_pos + _self._gem_size_half)
					_self._particle_effect:Kill(false)
					_self._start_time = _time
					_self._total_time = _self._delay
					_self._stage = 2
					
				end
			else
				if koef >= 1 then
					_self:InstantApply()
				end
			end
        end,

        InstantApply = function(_self)
			if not _self._is_dead then
				_self._cell.DecLock()
			end
            _self._is_dead = true
        end,

		IsDead = function(_self)
			return _self._is_dead
		end,
		
    }
	new_child_effect:Init(_fly_time, _start_pos, _cell, _delay)
	effects_widget.add_effect(new_child_effect)
end

--- функция созданяи эффекта зеленого тотема
totems_widget._totem_effect_create_functions[s11.CFieldCap.CapTypeGreen] = function ()
    local new_child_effect = 
    {
		_HitCellEffect = HitCellEffect,
		_AddGemOnField = AddGemOnField,
		_options = totems_widget._green_totem_options,
	
        Init = function(_self, _work_info)
			
			_self._stage = 0 -- первая стадия : разбивание гемов
			_self._new_gems_count = _work_info.perk1 -- количество добавляемых на поле камней
			local max_new_gems = game_window.game_field.GetMaxNewGemsCount()
			if max_new_gems < _self._new_gems_count then
				_self._new_gems_count = max_new_gems
			end
			-- список эффектов уничтожения фишек
			_self._hit_effects_list = {}
			-- обходим ячейки
			__sound("totem_green_use01")
			for i = 0,s11.ConstsFieldSizeX-1 do
				for j = 0,s11.ConstsFieldSizeY-1 do
					-- поулчаем ячейку и фишку
					local cell = game_window.game_field.GetCell(i, j)
					local cap = cell.GetCap()
					-- если ячейка свободна, а фишка есть и камень на ней тоже есть
					if cell.IsFree() and cap and cap.IsGem() then
						-- создаем и запоминаем эффекты удара по фишкам с гемами,
						-- что бы потом следить за тем когда они все помрут
						table.insert(_self._hit_effects_list, 
						             _self._HitCellEffect(cell, _self._options.lightning_start_pos))
					end
				end
			end
			if #_self._hit_effects_list > 0 then
				effects_widget.visual_effects:CreateInstantEffect("GreenTotemChest", _self._options.lightning_start_pos)
			end

        end,

        Draw = function(_self, _renderer)
        end,

        Update = function(_self, _time)
			
			-- проверяем какая щас стадия
			if _self._stage == 0 then
			    -- если стадия разрушения фишек с камнями
				-- тогда считаем эффекты разрушения
				for _,o in pairs(_self._hit_effects_list) do
					if not o:IsDead() then 
						-- если есть хоть один эффект жив, то стадия продолжается
						return
					end
				end
				-- если все эффекты мертвы, то смотрим нужно ли добавлять новые камни
				if _self._new_gems_count > 0 then
					__sound("totem_green_use02")
					-- если да, то меняем стадию на стадию добавления камней
					_self._stage = 1
					-- вычисляем оставшееся время отображения тотема
					_self._end_time = totems_widget._totem_work_time + totems_widget.effects_timer.Get().GetTime()
					-- создаем эффекты добавляения камней
					for i = 1,_self._new_gems_count do
						-- получаем ячейку для нового камня
						local cell = s11.game_helpers.GetRandomCellForGem(game_window.game_field)
						if not cell then
							-- если ячейка не получена, то значить они кончились
							-- и добавление можно прекращать
							break
						end
						-- если есть ячейка куда можно добавить новый камень
						-- содаем новый эффект добавления камня
						_self._AddGemOnField(_self._options.gem_start_pos, 
                                             cell, 
                                             _self._options.gem_fly_time,
											 _self._options.after_add_delay)
					end
				else
					-- если не нужно добавлять камни, то закрываем эффект тотема
					_self:InstantApply()
				end
			elseif _self._stage == 1 then
				-- если идет стадий добавления камней, то ждем
				-- пока закончится оставшееся время рабоыт тотема
				-- после чего его выключаем
				if _time > _self._end_time then
					_self:InstantApply()
				end
			else
				-- на всякий случай проверим не равна ли стадия чему-то другому
				-- тогда ругаемся и выходим из эффект тотема
				__message("GreenTotem: Unknown stage")
				_self:InstantApply()
				return
			end
			
        end,

        InstantApply = function(_self)
            _self._is_dead = true
        end,
		
		IsDead = function(_self)
			return _self._is_dead
		end
    }
    return new_child_effect
end
