local weather_manager = nil
--18.02.2008 - added dynamic weather

class "WeatherManager"
function WeatherManager:__init()
	self.update_time = 0
	self.update_level = ""
	self.last_hour = 0
    self.state={}
	self.graphs={}
	self.graphs_ini = ini_file("environment\\dynamic_weather_graphs.ltx")
	if not self.graphs_ini then
		abort("error when open weather_dynamic_graphs.ltx")
	end
end

-- Вызывается после load(). Состояние погоды уже загружено.
function WeatherManager:reset()
	printf("WeatherManager:WeatherManager():Reset()")
	-- Загрузить кондлист с погодой.
	local ini = ini_file("game.ltx")
	local weather = utils.cfg_get_string(ini, level.name(), "weathers", db.actor, false, "", "[default]")
	local postprocess = utils.cfg_get_string(ini, level.name(), "postprocess", db.actor, false, "")
	if postprocess ~= nil then
		printf("LEVEL POSTPROCESS: level: [%s], postprocess: [%s]", level.name(), postprocess)
		level.add_pp_effector(postprocess, 999, true)
	else
		printf("LEVEL POSTPROCESS: level: [%s], postprocess: [none]", level.name())
		level.remove_pp_effector(999)
	end
	if weather == "[default]" then		
		-- сетим дефолтовую погоду
		self.weather_list = xr_logic.parse_condlist(db.actor, level.name(), "weather", "[default]")
	else
		self.weather_list = xr_logic.parse_condlist(db.actor, level.name(), "weather", weather)
	end		
	self:select_weather(true)
	self.last_hour=level.get_time_hours()
end

-- Обновляем погоду раз в час.
function WeatherManager:update()
	if not benchmark.weather then
		if self.last_hour~=level.get_time_hours() then
		    self.last_hour=level.get_time_hours()
		    for lvl,st in pairs(self.state) do
				st.current_state=st.next_state
				st.next_state=get_next_state(st.graph,st.current_state)
		    end
		    -- Устанавливаем погоду на текущем уровне
		    self:select_weather(false)
		end
	end
end

function WeatherManager:select_weather(now)
	local weather = xr_logic.pick_section_from_condlist(db.actor, db.actor, self.weather_list)
	local graph=self:get_graph_by_name(weather)
	local weather_section_name=""
	-- Проверим, совпадает ли текущий граф уровня с полученным по кондлисту...
	if graph==nil then
		-- Переходим на статику
		self.state[weather]=nil
	    weather_section_name=weather
	else
		-- Новая погода - динамическая. Проверим, нужно ли менять/устанавливать граф
	    if self.state[weather]==nil or self.state[weather].graph_name~=weather then
			-- Граф изменился. Переходим на него.
			self.state[weather]=self:init_by_graph(graph,weather)
		-- else
			-- now = false
	    end
	    -- Получаем название секции по текущему состоянию. 		
	    local st=self.state[weather]
	    --weather_section_name="dw_"..st.current_state.."_"..st.next_state.."_"..level.get_time_hours()
	    weather_section_name="default_"..st.current_state
	end
	level.set_weather(weather_section_name,now);
	printf("WEATHER: '%s' now '%s'", weather_section_name, tostring(now))
	-- if xrs_news then
		-- xrs_news.news_call(1,1,nil,nil,weather_section_name,nil)
	-- end
end

-- Возвращает начальное состояние погоды.
function WeatherManager:init_by_graph(graph,graph_name)
  local cur_state=get_next_state(graph,"")
  local next_state=get_next_state(graph,cur_state)
  return {current_state=cur_state,next_state=next_state,graph_name=graph_name,graph=graph}
end

-- Возвращает одно из следующих состояний графа, согласно прописанным вероятностям.
function get_next_state(graph,state)
  local sum=0
  for st,prob in pairs(graph) do
		--if state==st then prob=prob*2 end
    sum=sum+prob
  end
  local rnd=math.random()*sum
  local next_state
  for st,prob in pairs(graph) do
		--if state==st then prob=prob*2 end
    next_state=st
    rnd=rnd-prob
    if (rnd<=0) then
      break
    end
  end
  return next_state
end

-- Устанавливаем состояние менеджера, распарсивая строку состояния
function WeatherManager:set_state_as_string(ss)
  self.state={}
    for lvlstring in string.gmatch(ss,"[^;]+") do
    local i,j,grname,curs,nexs=string.find(lvlstring,"([^=]+)=([^,]+),([^,]+)")
    if not grname then
      abort("WeatherManager:set_state_as_string: malformed state string. "..ss)
    end
    --local lvl_name=self:unpack_level(lvl)
    local current_state=self:unpack_state(curs)
    local next_state=self:unpack_state(nexs)
    local graph_name=self:unpack_graph_name(grname)
    local graph=self:get_graph_by_name(graph_name)
    if graph==nil then
    -- Старая сохранёнка? Будем считать что на этом уровне - статическая погода
    else
      self.state[graph_name]={current_state=current_state,next_state=next_state,graph_name=graph_name,graph=graph}
    end
  end
end

-- Преобразуем текущее состояние менеджера в строку
function WeatherManager:get_state_as_string()
  local lvlstrings={}
  for lvl_name,st in pairs(self.state) do
    --local lvl=self:pack_level(lvl_name)
    local curs=self:pack_state(st.current_state)
    local nexs=self:pack_state(st.next_state)
    local grn=self:pack_graph_name(st.graph_name)
    table.insert(lvlstrings,grn.."="..curs..","..nexs)
  end
  return table.concat(lvlstrings,";")
end

-- Получить граф (таблицу переходов состояний погоды) по его названию и названию игрового уровня
function WeatherManager:get_graph_by_name(name)
	if not self.graphs[name] then		
		self.graphs[name] = xr_s.parse_ini_section_to_array(self.graphs_ini,name)
	end
	return self.graphs[name]
end

-- Запаковать название вершины графа
function WeatherManager:pack_state(state)
  -- Пока паковать не будем.
  return state
end

-- Распаковать название вершины графа
function WeatherManager:unpack_state(st)
  -- Пока паковать не будем
  return st
end

-- Запаковать название графа переходов погоды
function WeatherManager:pack_graph_name(graph_name)
  -- Пока паковать не будем.
  return graph_name
end

-- Распаковать название графа переходов погоды
function WeatherManager:unpack_graph_name(grn)
  -- Пока паковать не будем
  return grn
end

function WeatherManager:load(F)
	set_save_marker(F, "load", false, "WeatherManager")
	printf("WEATHER LOAD")
	--self.update_level  = F:r_stringZ();
	local state_string = F:r_stringZ();
	printf("str = "..state_string)
	if state_string == "" then
		printf("str = empty string")
	end
	self:set_state_as_string(state_string)
	self.update_time = F:r_u32();
	set_save_marker(F, "load", true, "WeatherManager")
end

function WeatherManager:save(F)
	set_save_marker(F, "save", false, "WeatherManager")
	printf("WEATHER SAVE")
	--F:w_stringZ(self.update_level);
	printf("str = "..tostring(self:get_state_as_string()))
	if self:get_state_as_string() == "" then
		printf("str = empty string")
	end
	F:w_stringZ(self:get_state_as_string())
	F:w_u32(self.update_time)
	set_save_marker(F, "save", true, "WeatherManager")
end

function get_weather_manager ()
	if weather_manager == nil then
		weather_manager = WeatherManager()
	end
	return weather_manager
end
