-- DAWS_Package for DCSW - module save mission
local MainVersion = "2"
local SubVersion = "3"
local Build = "2351"

-- THANKS TO (cronological order):
	-- Rider (AMVI)
	-- Grimes (ED community)
	-- MBot (ED community)
	-- xcom (ED community)
	-- Ian (ED community)
	-- vicx (ED community)
	-- Pikey (ED community)
	-- ESAC_Matador (ED community)
	-- uboats (ED community)

	-- MANUAL USER VARIABLES
	
	local ExcludeTag				= "Xcl_" -- using this tag as a prefix for group name will prevent those groups to be tracked by DAWS. If killed or moved, those groups won't be affected.	
	local AutoSaveFileName			= "DAWS_AutoSave.miz" -- this will be the name of the autosaved miz - -"DAWS_AutoSave_"
	local NightMission 				= true -- if set "false", it will prevent to set up mission in evening and night hours.
	local FixedSavePath				= "C:/DAWSautosave/YourCustomFileName.miz"-- lfs.writedir() .. "Missions/" .. "YourCustomFileName.miz" -- this will set the saving position for UseFixedPath variable, when it's true
	
	
-- ################################################################################################################################
-- ################################################################################################################################
-- ################################################################################################################################
-- ################################################################################################################################
-- ################################################################################################################################
-- ################################################################################################################################
-- ################################################################################################################################
	
	--
	-- local function copy
	local base 						= _G
	local require 					= base.require
	local table 					= base.table
	local math 						= base.math
	local pairs 					= base.pairs
	local ipairs 					= base.ipairs
	local print 					= base.print
	local io 						= base.io
	local lfs 						= base.lfs
	local os 						= base.os
	local zip 						= minizip
	local loadstring 				= base.loadstring
	local loadlib					= base.loadlib
	--]]--
	
	--required modules
	minizip 						= require('minizip')
	
	-- common directory listing
	local mistdirectory 			= lfs.writedir() .. "AMVI/Common/Code/"
	--local subdirectory 			= lfs.writedir() .. "AMVI/SaveMission/"
	--local tabledirectory  		= lfs.writedir() .. "AMVI/SaveMission/Tables/"
	local moddirectory 				= moddirectorySM 	--lfs.writedir() .. "AMVI/SaveMission/"
	local debugdirectory  			= debugdirectorySM 	--lfs.writedir() .. "AMVI/SaveMission/Debug/"
	local missionfilesdirectory 	= missionfilesdirectoryDP
	local logsdirectory				= logsdirectoryDP
	
	-- common export variables
	local exportfiletype 			= ".csv"
	--reportfiletype 				= ".doc"
	local configfiletype 			= ".csv"
	local tss 						= ";"
	local NEWstartTime 				= nil
	local NEWstartDateYear			= nil
	local NEWstartDateMonth			= nil
	local NEWstartDateDay			= nil
	local NEWstartTime				= nil			
	local NEWstartDateDay			= nil
	local NEWstartDateYear			= nil
	local NEWstartDateMonth			= nil
	local NEWweather 				= nil -- ##### CHECK #####	
	
	--##### INTERNAL VARIABLES
	local MissionStartTimeSim 		= timer.getTime0()
	local debugProcess 				= DAWSdebugProcess
	local superDebugProcess			= true -- this one prints out tables and file for deeper data checks
	local baseGcounter 				= 10000
	local saveCounter				= 0
	local StaticStartNumber 		= 0
	local loadedMissionPath 		= "" -- not used at the moment
	local tblDictEntries			= {}
	local tblDeadUnits				= {}
	local DAWSAIEu_tag				= "DAWSAIEu"
	local LoadInternalFiles			= true -- will be automatically set false after first call
	--local theAutosaveFilename_num	= 1
	
	--##### EXTERNAL VARIABLES (DAWS Package integration)
	DAWS_SM_running					= true
	DAWS_SM_TimerSetting			= nil --> will be used from DAWS AI Enhancement
	
	-- ##### LOAD MAIN TABLE
	
	-- create DAWS repository if not there
	--
	if not DAWS then
		DAWS = {}
	end
	
	if not debugProcess then
		env.info(("DAWS DebugProcess variable is nil!"))
	end	

	-- imported basicSerialize
	function IntegratedbasicSerialize(s)
		if s == nil then
			return "\"\""
		else
			if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then
				return tostring(s)
			elseif type(s) == 'string' then
				return string.format('%q', s)
			end
		end
	end
	--]]--

	-- imported slmod.serialize
	function Integratedserialize(name, value, level)
		-----Based on ED's serialize_simple2
		local basicSerialize = function (o)
		  if type(o) == "number" then
			return tostring(o)
		  elseif type(o) == "boolean" then
			return tostring(o)
		  else -- assume it is a string
			return IntegratedbasicSerialize(o)
		  end
		end

		local serialize_to_t = function (name, value, level)
		----Based on ED's serialize_simple2


		  local var_str_tbl = {}
		  if level == nil then level = "" end
		  if level ~= "" then level = level.."  " end

		  table.insert(var_str_tbl, level .. name .. " = ")

		  if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then
			table.insert(var_str_tbl, basicSerialize(value) ..  ",\n")
		  elseif type(value) == "table" then
			  table.insert(var_str_tbl, "\n"..level.."{\n")

			  for k,v in pairs(value) do -- serialize its fields
				local key
				if type(k) == "number" then
				  key = string.format("[%s]", k)
				else
				  key = string.format("[%q]", k)
				end

				table.insert(var_str_tbl, Integratedserialize(key, v, level.."  "))

			  end
			  if level == "" then
				table.insert(var_str_tbl, level.."} -- end of "..name.."\n")

			  else
				table.insert(var_str_tbl, level.."}, -- end of "..name.."\n")

			  end
		  else
			print("Cannot serialize a "..type(value))
		  end
		  return var_str_tbl
		end

		local t_str = serialize_to_t(name, value, level)

		return table.concat(t_str)
	end
	--]]--

	-- imported slmod.serializeWithCycles
	function IntegratedserializeWithCycles(name, value, saved)
		local basicSerialize = function (o)
			if type(o) == "number" then
				return tostring(o)
			elseif type(o) == "boolean" then
				return tostring(o)
			else -- assume it is a string
				return IntegratedbasicSerialize(o)
			end
		end

		local t_str = {}
		saved = saved or {}       -- initial value
		if ((type(value) == 'string') or (type(value) == 'number') or (type(value) == 'table') or (type(value) == 'boolean')) then
			table.insert(t_str, name .. " = ")
			if type(value) == "number" or type(value) == "string" or type(value) == "boolean" then
				table.insert(t_str, basicSerialize(value) ..  "\n")
			else

				if saved[value] then    -- value already saved?
					table.insert(t_str, saved[value] .. "\n")
				else
					saved[value] = name   -- save name for next time
					table.insert(t_str, "{}\n")
					for k,v in pairs(value) do      -- save its fields
						local fieldname = string.format("%s[%s]", name, basicSerialize(k))
						table.insert(t_str, IntegratedserializeWithCycles(fieldname, v, saved))
					end
				end
			end
			return table.concat(t_str)
		else
			return ""
		end
	end
	--]]--

	-- imported slmod.serializeWithCycles
	function IntegratedGetUnzippedMission(t_window) -- OK

		t_window = t_window or 3600 -- default: if t_window not specified, look at all files newer than 1 hour
		local run_t = os.time()
		local mis_path, mis_t
		local path =  lfs.tempdir()

		for file in lfs.dir(path) do
			if file and file:sub(1,1) == '~' then
				local fpath = path .. '/' .. file
				local mod_t = lfs.attributes(fpath, 'modification')
				if mod_t and math.abs(run_t - mod_t) <= t_window then
					local f = io.open(fpath, 'r')
					if f then
						local fline = f:read()
						if fline and fline:sub(1,7) == 'mission' and (not mis_t or mod_t > mis_t) then -- found an unzipped mission file, and either none was found before or this is the most recent
							mis_t = mod_t
							mis_path = fpath
						end
						f:close()
					end
				end
			end
		end

		if mis_path then -- a mission file was found
			local f = io.open(mis_path, 'r')
			if f then
				local mission = f:read('*all')
				f:close()

				if debugProcess == true then
					env.info(("--> mission file in tempdir opened"))	  -- Printa solo conferma che ha letto la variabile mission.
				end

				return mission
			end
		end
	end
	--]]--
	
	-- old mist.utils.tableShow
	DAWS.tableShow = function(tbl, loc, indent, tableshow_tbls) --based on serialize_slmod, this is a _G serialization
		tableshow_tbls = tableshow_tbls or {} --create table of tables
		loc = loc or ""
		indent = indent or ""
		if type(tbl) == 'table' then --function only works for tables!
			tableshow_tbls[tbl] = loc
			
			local tbl_str = {}

			tbl_str[#tbl_str + 1] = indent .. '{\n'
			
			for ind,val in pairs(tbl) do -- serialize its fields
				if type(ind) == "number" then
					tbl_str[#tbl_str + 1] = indent 
					tbl_str[#tbl_str + 1] = loc .. '['
					tbl_str[#tbl_str + 1] = tostring(ind)
					tbl_str[#tbl_str + 1] = '] = '
				else
					tbl_str[#tbl_str + 1] = indent 
					tbl_str[#tbl_str + 1] = loc .. '['
					tbl_str[#tbl_str + 1] = IntegratedbasicSerialize(ind)
					tbl_str[#tbl_str + 1] = '] = '
				end
						
				if ((type(val) == 'number') or (type(val) == 'boolean')) then
					tbl_str[#tbl_str + 1] = tostring(val)
					tbl_str[#tbl_str + 1] = ',\n'		
				elseif type(val) == 'string' then
					tbl_str[#tbl_str + 1] = IntegratedbasicSerialize(val)
					tbl_str[#tbl_str + 1] = ',\n'
				elseif type(val) == 'nil' then -- won't ever happen, right?
					tbl_str[#tbl_str + 1] = 'nil,\n'
				elseif type(val) == 'table' then
					if tableshow_tbls[val] then
						tbl_str[#tbl_str + 1] = tostring(val) .. ' already defined: ' .. tableshow_tbls[val] .. ',\n'
					else
						tableshow_tbls[val] = loc ..  '[' .. IntegratedbasicSerialize(ind) .. ']'
						tbl_str[#tbl_str + 1] = tostring(val) .. ' '
						tbl_str[#tbl_str + 1] = DAWS.tableShow(val,  loc .. '[' .. IntegratedbasicSerialize(ind).. ']', indent .. '    ', tableshow_tbls)
						tbl_str[#tbl_str + 1] = ',\n'  
					end
				elseif type(val) == 'function' then
					if debug and debug.getinfo then
						local fcnname = tostring(val)
						local info = debug.getinfo(val, "S")
						if info.what == "C" then
							tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', C function') .. ',\n'
						else 
							if (string.sub(info.source, 1, 2) == [[./]]) then
								tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')' .. info.source) ..',\n'
							else
								tbl_str[#tbl_str + 1] = string.format('%q', fcnname .. ', defined in (' .. info.linedefined .. '-' .. info.lastlinedefined .. ')') ..',\n'
							end
						end
						
					else
						tbl_str[#tbl_str + 1] = 'a function,\n'	
					end
				else
					tbl_str[#tbl_str + 1] = 'unable to serialize value type ' .. IntegratedbasicSerialize(type(val)) .. ' at index ' .. tostring(ind)
				end
			end
			
			tbl_str[#tbl_str + 1] = indent .. '}'
			return table.concat(tbl_str)
		end
	end
	--]]--
	
	-- old mist.debug.dump_G
	DAWS.dumpTable = function(fname, tabledata)
		if lfs and io then
			local fdir = lfs.writedir() .. [[Logs\]] .. fname
			local f = io.open(fdir, 'w')
			f:write(DAWS.tableShow(tabledata))
			f:close()
		end
	end
	--]]--		
	
	DAWS.fileExist = function(name)
		local f=io.open(name,"r")
		if f~=nil then 
			io.close(f)
			return true 
		else 
			io.close(f) 
			return false 
		end
	end
	--]]--

	local  CreateStatics 					= CreateStaticsDP
	local  HiddenStatics 					= HiddenStaticsDP
	local  MapObjectPersitence 				= MapObjectPersitenceDP
	local  KeepGroupsRoutes 				= KeepGroupsRoutesDP
	local  AirUnitTracked 					= AirUnitTrackedDP
	local  TrackAddedGroups 				= TrackAddedGroupsDP
	local  TrackAddedInfantry 				= TrackAddedInfantryDP
	local  timer_options 					= timer_optionsDP
	local  theMessageState 					= theMessageStateDP
	local  RadioMenuVariable 				= RadioMenuVariableDP
	local  RadioMenuSingleGroup				= RadioMenuSingleGroupDP
	local  AutoSaveEnable 					= AutoSaveEnableDP
	local  UseFixedPath 					= UseFixedPathDP
	local  KeepContinousMission 			= KeepContinousMissionDP
	local  UpdateSceneryDate				= UpdateSceneryDateDP
	local  FixedPath						= FixedPathDP
	--]]--
	
	-- add reading fixedpath.lua
	if lfs.attributes(missionfilesdirectory .. "fixedpath.lua") then	
		local i = io.open(missionfilesdirectory .. "fixedpath.lua", "r")
		FixedPath = i:read("*a") -- critical: how to evaluate a valid path string?
		if debugProcess == true and FixedPath ~= nil then
			env.info(("DAWS option: FixedPath is = " .. tostring(FixedPath)))
		end
		i:close()
		if FixedPath == nil then
			UseFixedPath = false
			if debugProcess == true and FixedPath ~= nil then
				env.info(("DAWS option: FixedPath is nil so UseFixedPath is moved to false"))
			end				
		end
	end
	--]]--
	
	
	--###########################################   MOSS CODE BY RIDER   ######################################################

	function MOSSGetWorldObjects()
	  local res = nil;
	  local res_str, success = net.dostring_in('export', "return Integratedserialize('wobjs', LoGetWorldObjects(), '')");
	  if not success then

		if debugProcess == true then
			env.info(("--> MOSSGetWorldObjects() non è riuscito a prendere i contenuti, res_str è nil."))	  -- Printa solo conferma che ha letto la variabile mission.
		end

		return nil
	  end
	  return res_str;
	end
	--]]--

	-- update units and write the new mission file /slightly modified to suit updates
	function MOSSSave(NewDictPath)
	
	  if not gMOSSMix then
		if debugProcess == true then
			env.info(("--> MOSSSave() non ha trovato contenuti in gMOSSMix"))	  -- Printa solo conferma che ha letto la variabile mission.
		end
		return false
	  end

		if debugProcess == true then
			env.info(("--> MOSSSave() sta per caricare gMOSSMix"))	  -- Printa solo conferma che ha letto la variabile mission.
		end	 	  

	  local mixFun, mErrStr = loadstring(gMOSSMix); -- crea una funzione con il contenuto della stringa
	  
		if debugProcess == true then
			env.info(("--> MOSSSave() ha caricato gMOSSMix" .. "\n"))	  -- Printa solo conferma che ha letto la variabile mission.
		end	  

	  if mixFun then   -- and objsFun
		local tempenv = env
		local env = { };
		setfenv(mixFun, env); -- assegna la funzione all' ENV
		mixFun();
		
		-- check dead units
		for id, MEunitData in pairs(mist.DBs.MEunitsById) do
			local isGroundUnit = nil
			local isPlaneUnit = nil
			local MaybeDead = MEunitData.unitId -- unitName

			--check in ME units
			local VerifiedDead = false -- true
			
			for id,DeadunitData in pairs(mist.DBs.deadObjects) do
				if DeadunitData then
					if DeadunitData.objectData then
						local SureDead = DeadunitData.objectData.unitId
						if SureDead then -- check if the unit exist
							--print("Dead unitId: " .. DeadunitData.objectData.unitId)
							if SureDead == MaybeDead then
								if DeadunitData.objectData.category == "vehicle" or DeadunitData.objectData.category == "ship" or DeadunitData.objectData.category == "static" then --this filter prevent to kill flights.				
									VerifiedDead = true
									isGroundUnit = true
								elseif DeadunitData.objectData.category == "plane" or DeadunitData.objectData.category == "helicopter" then
									VerifiedDead = true
									isPlaneUnit = true								
								else	
									VerifiedDead = true
								end
							end
						end
					end
				end
			end
			
			--check in Spawned
			for id,SpawnData in pairs(mist.DBs.dynGroupsAdded) do
				if SpawnData then
					if SpawnData.units then
						for _, SpawnunitData in pairs(SpawnData.units) do
							local SureDead = SpawnunitData.unitId
							if SureDead then -- check if the unit exist
								if SureDead == MaybeDead then
									if debugProcess == true then
										tempenv.info(("--> MOSSSave(): l'unità è morta"))	  -- Printa solo conferma che ha letto la variabile mission.
									end	  							
									if SpawnunitData.category == "vehicle" or SpawnunitData.category == "ship" or SpawnunitData.category == "static" then --this filter prevent to kill flights.				
										if debugProcess == true then
											tempenv.info(("--> MOSSSave(): l'unità è veicolo o nave o statico"))	  -- Printa solo conferma che ha letto la variabile mission.
										end
										VerifiedDead = true
										isGroundUnit = true
									elseif SpawnunitData.category == "plane" or SpawnunitData.category == "helicopter" then
										VerifiedDead = true
										isPlaneUnit = true
										if debugProcess == true then
											tempenv.info(("--> MOSSSave(): l'unità è elicottero o velivolo"))	  -- Printa solo conferma che ha letto la variabile mission.
										end									
									else	
										VerifiedDead = true
									end
								end
							end
						end
					end
				end
			end			
			
			if VerifiedDead == true then
				--local coalitionID,coalition,countryID,country,kindID,kind,groupID,group,unitID,unit = MOSSUnitLookup(env.mission, MaybeDead);
				--if MEunitData.categoryStatic ~= "Cargos" then
					MOSSKillUnit(env.mission, MaybeDead, isGroundUnit, isPlaneUnit, MEunitData);
				--end
				--if Buildstatic == true then
				--	DAWS.createStatic(env.mission, MaybeDead, coalitionID, countryID)
				--end
			end
			
		end
		--]]--
		
		--add dyn added group
		local MaxDict = env.mission.maxDictId	
		function DAWS.addSpawned(mission) -- OK
			local alreadyInserted = {}
			for id, spawnedData in pairs (mist.DBs.dynGroupsAdded) do

				if spawnedData.category == "plane" or spawnedData.category == "helicopter" then
					if debugProcess == true then
						tempenv.info(("DAWS.addSpawned tried to spawn helo or plane, stopped"))
					end					
				else
					-- check if the spawned group has at least an alive unit
					if debugProcess == true then
						tempenv.info(("DAWS.addSpawned started checking groupID " .. spawnedData.groupId .. ", groupName: " .. spawnedData.name))
					end

					-- check mist group duplicate (error with 4.0.57)
					for _, insertedName in pairs(alreadyInserted) do
						if insertedName == spawnedData.groupName then
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned, groupName: " .. spawnedData.name .. " has already been added"))
							end					
							return
						end
					end
					
					-- check if the group already exist by name (means it's teleported), than kill original ID
					for id, MEgroupsData in pairs(mist.DBs.MEgroupsById) do
						local existName = MEgroupsData.groupName
						if spawnedData.groupName == existName then
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned, groupName: " .. spawnedData.name .. " has been teleported"))
							end
							
							local MEgroupkillId = MEgroupsData.groupId
							
							for _, KillUnitData in pairs(MEgroupsData.units) do
								local isGroundUnit = nil
								local isPlaneUnit = nil
								local MEunitkillId = KillUnitData.unitId
							
								if KillUnitData.category == "vehicle" or KillUnitData.category == "ship" or KillUnitData.category == "static" then --this filter prevent to kill flights.				
									isGroundUnit = true
								elseif KillUnitData.category == "plane" or KillUnitData.category == "helicopter" then
									isPlaneUnit = true								
								end							
							
								MOSSKillUnit(env.mission, MEunitkillId, isGroundUnit, isPlaneUnit);
							end
						end
					end
					--]]--
					
					for _, insertedName in pairs(alreadyInserted) do
						if insertedName == spawnedData.groupName then
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned, groupName: " .. spawnedData.name .. " has already been added"))
							end					
							return
						end
					end					
					
					
					-- verify that this group has at least one alive unit
					local checkAlive = false			
					for id, spUnitsData in pairs (spawnedData.units) do
						local checkId = spUnitsData.unitId
						for id, alData in pairs (mist.DBs.aliveUnits) do
							if alData.unitId == checkId then
								checkAlive = true
							end
						end
					end
					
					-- if alive proceed
					if checkAlive == true then
						if debugProcess == true then
							tempenv.info(("DAWS.addSpawned checked groupID " .. spawnedData.groupId .. ", groupName: " .. spawnedData.name .. " is alive"))
						end				
						

						-- check coalition existence
						local coalitionID = spawnedData.coalition
						if not mission.coalition[coalitionID] then
							mission.coalition[coalitionID] = {}
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned created coalitionId " .. coalitionID))
							end						
						end
						
						-- check country existence
						local countryID = nil
						for numCoa, coaName in pairs(mission.coalitions) do
							for numCtr, ctrId in pairs(coaName) do
								if spawnedData.countryId == ctrId then
									countryID = numCtr
									if debugProcess == true then
										tempenv.info(("DAWS.addSpawned countryID = ".. countryID))
									end								
								end
							end
						end
						
						-- stop everything if countryID isn't found
						if countryID == nil then 
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned countryID result null"))
							end					
							return 
						end
						
						if not mission.coalition[coalitionID]["country"] then
							mission.coalition[coalitionID]["country"] = {}
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned created country subtable"))
							end							
						end
						
						if not mission.coalition[coalitionID]["country"][countryID] then
							mission.coalition[coalitionID]["country"][countryID] = {}
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned created countryId " .. countryID))
							end							
						end				
						
						-- check category existence
						local categoryDEF = spawnedData.category
						if not mission.coalition[coalitionID]["country"][countryID][categoryDEF] then
							mission.coalition[coalitionID]["country"][countryID][categoryDEF] = {}
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned created category table " .. categoryDEF))
							end							
						end

						-- check group existence
						if not mission.coalition[coalitionID]["country"][countryID][categoryDEF]["group"] then
							mission.coalition[coalitionID]["country"][countryID][categoryDEF]["group"] = {}
							if debugProcess == true then
								tempenv.info(("DAWS.addSpawned created group subtable"))
							end							
						end	
						local groupTable = mission.coalition[coalitionID]["country"][countryID][categoryDEF]["group"]				

						-- create DictKey_GroupName dict
						MaxDict = MaxDict+1
						local GrpDictEntry = "DictKey_GroupName_" .. MaxDict
						tblDictEntries[GrpDictEntry] = spawnedData.groupName
						MaxDict = MaxDict+1
						local WptDictEntry = "DictKey_WptName_" .. MaxDict
						tblDictEntries[WptDictEntry] = spawnedData.groupName					
			
						-- build gUnits table
						local gUnits = {}
						for spId, spData in pairs(spawnedData.units) do
							local checkAlive = false			
							local checkId = spData.unitId
							local checkName = spData.unitName
							local unit = Unit.getByName(checkName)
							local uX = nil
							local uY = nil
							if unit then
								if unit:getLife() > 1 then
									checkAlive = true
									uX = unit:getPosition().p.x
									uY = unit:getPosition().p.z
								end
							end
							--for id, alData in pairs (mist.DBs.aliveUnits) do
								--if alData.unitId == checkId then
									--checkAlive = true
									--uX = alData.pos.x
									--uY = alData.pos.z
								--end
							--end
							
							if checkAlive == true then		
								
								-- filter infatry units
								local add_unit = true
								if string.find(spData.unitName,DAWSAIEu_tag) then
									add_unit = false
								elseif spData.type == "Soldier M4" 
									or spData.type == "Soldier M249"
									or spData.type == "Stinger manpad GRG"
									or spData.type == "Stinger comm"
									or spData.type == "2B11 mortar"
									or spData.type == "Infantry AK"
									or spData.type == "Paratrooper AKS-74"
									or spData.type == "Paratrooper RPG-16"
									or spData.type == "SA-18 Igla-S manpad"
									or spData.type == "SA-18 Igla-S comm"
									then
									if TrackAddedInfantry == false or TrackAddedInfantry == nil then
										add_unit = false
									end
								end
								
									
								if add_unit == true then
									MaxDict = MaxDict+1
									local UnitDictEntry = "DictKey_UnitName_" .. MaxDict
									tblDictEntries[UnitDictEntry] = spData.unitName								
									-- create loca table
									gUnits[#gUnits + 1] =
													{
														["type"] = spData.type,
														["transportable"] = 
														{
															["randomTransportable"] = false,
														}, -- end of ["transportable"]
														["unitId"] = spData.unitId,
														["skill"] = spData.skill,
														["y"] = uY,
														["x"] = uX,
														["name"] = UnitDictEntry,
														["playerCanDrive"] = true,
														["heading"] = spData.heading,
													}
								end
							end
							--]]--
						end			
						--]]--
						
						local gName = spawnedData.groupName
						local gId = spawnedData.groupId	
						
						if table.getn(gUnits) > 0 then
						
							-- ggroupTable variables		
							local gPosx = gUnits[1]["x"]
							local gPosy = gUnits[1]["y"]
							local gAlt = land.getHeight({x = gPosx, y = gPosy})

							--add the group to the mission table
							NewGroupTable = 
										{
											["visible"] = false,
											["taskSelected"] = true,
											["route"] = 
											{
												["spans"] = 
												{
												}, -- end of ["spans"]
												["points"] = 
												{
													[1] = 
													{
														["alt"] = gAlt,
														["type"] = "Turning Point",
														["ETA"] = 0,
														["alt_type"] = "BARO",
														["formation_template"] = "",
														["y"] = gPosy,
														["x"] = gPosx,
														["name"] = WptDictEntry,
														["ETA_locked"] = true,
														["speed"] = 0,
														["action"] = "Off Road",
														["task"] = 
														{
															["id"] = "ComboTask",
															["params"] = 
															{
																["tasks"] = 
																{
																}, -- end of ["tasks"]
															}, -- end of ["params"]
														}, -- end of ["task"]
														["speed_locked"] = true,
													}, -- end of [1]
												}, -- end of ["points"]
											}, -- end of ["route"]
											["groupId"] = gId,
											["tasks"] = 
											{
											}, -- end of ["tasks"]
											["hidden"] = false,
											["units"] = gUnits,
											["y"] = gPosx,
											["x"] = gPosy,
											["name"] = GrpDictEntry,
											["start_time"] = 0,
											["task"] = "Ground Nothing",
										}
							--]]-- add table
							
							groupTable[#groupTable + 1] = NewGroupTable
							alreadyInserted[#alreadyInserted + 1] = gName
							--]]--
						end
						
						if debugProcess == true and NewGroupTable ~= nil then
							tempenv.info(("DAWS.addSpawned cloned the group ".. gName .. " inside the mission table"))
						elseif debugProcess == true and NewGroupTable == nil then
							tempenv.info(("DAWS.addSpawned failed to clone group ".. gName .. " inside the mission table"))
						end
						
					else
						if debugProcess == true then
							tempenv.info(("DAWS.addSpawned do not found any alive units for that group"))
						end					
					end
				end -- category filter
				--]]--
				
			end
		end
		--]]--
		
		-- add spawned groups
		if TrackAddedGroups == true then
			DAWS.addSpawned(env.mission)
		end	
		
		-- add statics groups
		if CreateStatics == true then
			DAWS.createStatics(env.mission)
		end
		
		-- update units positions
		for ID,Object in pairs(mist.DBs.aliveUnits) do -- wobjs viene creato da objsFun  - mist.DBs.MEunitsById
		  if Object then
			MOSSUpdateUnit(env.mission, Object, not AirUnitsUpd);  --not AirUnitsUpd
		  end
		end
		
		-- reindex statics for cargo fix when logistic is enabled
		for coalitionID,coalition in pairs(env.mission["coalition"]) do
			for countryID,country in pairs(coalition["country"]) do
				for attrID,attr in pairs(country) do
					if (type(attr)=="table") and attrID == "static" then
						local tempGroup = attr["group"]
						local newGroup = {}
						for groupID,group in pairs(tempGroup) do		
							newGroup[#newGroup + 1] = group
						end
						attr["group"] = newGroup
					end
				end
			end
		end
		
		-- update startime
		DAWS.UpdateMissionStartTime()
		env.mission.start_time = NEWstartTime
		env.mission["date"]["Day"] = NEWstartDateDay
		env.mission["date"]["Year"] = NEWstartDateYear
		env.mission["date"]["Month"] = NEWstartDateMonth		
		
		env.mission.maxDictId = MaxDict

		-- generate output dictionary file
		local dictTable = nil
		local dictTablefile = io.open(NewDictPath, "r")
		if dictTablefile then
			dictTablefileReaded = dictTablefile:read('*all')
			if debugProcess == true then
				tempenv.info(("DAWS.MOSSsave found dictTablefile"))
			end					
			tmp_dict = loadstring(dictTablefileReaded)
			if tmp_dict then
				if debugProcess == true then
					tempenv.info(("DAWS.MOSSsave loaded tmp_dict"))
				end					
				tmp_dict()
				dictTable = dictionary
				if debugProcess == true then
					tempenv.info(("DAWS.MOSSsave created dictTable"))
				end
				for id, value in pairs (tblDictEntries) do
					dictTable[id] = value
					if debugProcess == true then
						tempenv.info(("DAWS.MOSSsave inserted " .. id .. " in dictTable"))
					end				
				end
			end
			dictTablefile:close()
		end
		
		lfs.mkdir(missionfilesdirectory .. "Temp/")		
		
		-- generate output mission file
		local fName = "mission"

		local missName = missionfilesdirectory .. "Temp/" .. fName
		local outFile = io.open(missName, "w");
		local newMissionStr = IntegratedserializeWithCycles('mission', env.mission);
		outFile:write(newMissionStr);
		io.close(outFile);

		local d_fName = "dictionary"
		local dictName = missionfilesdirectory .. "Temp/" .. d_fName
		local d_outFile = io.open(dictName, "w");
		local newDictStr = IntegratedserializeWithCycles('dictionary', dictTable);
		d_outFile:write(newDictStr);
		io.close(d_outFile);
		
		if DAWS_mountedInfantryTable_SM and table.getn(DAWS_mountedInfantryTable_SM) > 0 then		

			local ea_dm_fName = "DAWS_mountedInfantryTable_SM"
			local ea_dm_table = missionfilesdirectory .. "Temp/" .. ea_dm_fName
			local ea_dm_outFile = io.open(ea_dm_table, "w");
			local DAWS_mountedInfantryTable_SM_str = IntegratedserializeWithCycles('DAWS_mountedInfantryTable_SM', DAWS_mountedInfantryTable_SM);
			ea_dm_outFile:write(DAWS_mountedInfantryTable_SM_str);
			io.close(ea_dm_outFile);		
		
		
		end

		
		if superDebugProcess == true then
			DAWS.dumpTable("new_mission.lua", env.mission)									
		end	
		
	  else
		return false
	  end

	  return true
	end
	--]]--

	-- find a unit by name in the mission table
	function MOSSUnitLookup(mission, uID)
	  --env.info(("MOSSUnitLookup is looking for uID " .. uID))
	  for coalitionID,coalition in pairs(mission["coalition"]) do
		for countryID,country in pairs(coalition["country"]) do
		  for attrID,attr in pairs(country) do
			if (type(attr)=="table") then
			  for groupID,group in pairs(attr["group"]) do
				if (group) then
				  for unitID,unit in pairs(group["units"]) do
					if unit.unitId then
					  --env.info(("comparing unit " .. unit.unitId .. " with uID " .. uID))
					  if unit.unitId == uID then
						if debugProcess == true then
							env.info(("MOSSUnitLookup found unit " .. uID))
						end
						return coalitionID,coalition,
							countryID,country,
							attrID,attr,
							groupID,group,
							unitID,unit;
					  --else
						-- find a way to retrieve the info from the spawned table
					  end
					end
				  end
				end
			  end
			end
		  end
		end
	  end
	  return nil,nil,nil,nil,nil,nil,nil,nil,nil,nil;
	end
	--]]--
	
	-- kill a unit (or mark dead if static)
	function MOSSKillUnit(mission, uID, isGroundUnit, isPlaneUnit, MEunitData)

		if debugProcess == true then
			env.info(("MOSSKillUnit is killing unit uID: " .. tostring(uID) .. ", category: " .. tostring(MEunitData.categoryStatic) .. ", name: " .. tostring(MEunitData.unitName)))
		end	
	
		local GoOnWithPlanes = nil
		if AirUnitTracked == true then
			GoOnWithPlanes = isPlaneUnit
		end
	  
		local Buildstatic = false	
	  
		local coalitionID,coalition,
			countryID,country,
			kindID,kind,
			groupID,group,
			unitID,unit = MOSSUnitLookup(mission, uID);

			-- check exclude
		local gName = env.getValueDictByKey(group.name)
		local uName = env.getValueDictByKey(unit.name)
		
		if string.find(gName, ExcludeTag) then
			if debugProcess == true then
				env.info(("MOSSKillUnit found a unit part of a group to be excluded from killing: " .. gName))
			end
			return
		end		  
		  
		if not unit then
			if debugProcess == true then
				env.info(("--> MOSSKillUnit() non ha trovato l'unità da uccidere: ".. uID .. "\n"))	  -- Printa solo conferma che ha letto la variabile mission.
			end
			return -- break the function
		end
		
		-- if the unit is static, mark as dead and leave
		if (kindID == "static") then
			if MEunitData.categoryStatic == "Cargos" then
				table.remove(group.units, unitID);
				if debugProcess == true then
					env.info(("MOSSKillUnit killed a cargo unit"))
				end					
				if table.getn(group.units) == 0 then  		-- if next(group.units) == nil then
					if debugProcess == true then
						env.info(("MOSSKillUnit killed a cargo group"))
					end				
					kind.group[groupID] = nil;
					
					if table.getn(kind.group) == 0 then 	-- if next(kind.group) == nil then
						if debugProcess == true then
							env.info(("MOSSKillUnit killed a cargo country"))
						end						
						country[kindID] = nil;
					end
					
				end				
			else
				group["dead"] = true;
				--isVehicle = false
			end
		else
	  
			if isGroundUnit ~= nil then
				table.remove(group.units, unitID);
				UnitType = unit.type
				-- remove subtree up to country if empty
				local next = next;
				if next(group.units) == nil then
					kind.group[groupID] = nil;
					if next(kind.group) == nil then
						country[kindID] = nil;
					end
				end
			end
		
			if GoOnWithPlanes == true then
				table.remove(group.units, unitID);
				UnitType = unit.type
				-- remove subtree up to country if empty
				local next = next;
				if next(group.units) == nil then

					kind.group[groupID] = nil;
					if next(kind.group) == nil then
						country[kindID] = nil;
					end
				end
			end		
		
		end
	  
	end
	--]]--

	-- update unit position in respect to world object provided
	function MOSSUpdateUnit(mission, object, keepAUPos)
		if not object.unitId then
			return
		end
		
		local coalitionID,coalition,
			countryID,country,
			kindID,kind,
			groupID,group,
			unitID,unit = MOSSUnitLookup(mission, object.unitId)
		
		if group and unit then -- fixed missing group updates (see spawned ones)
		
			-- check exclude
			local gName = env.getValueDictByKey(group.name)
			if string.find(gName, ExcludeTag) then
				if debugProcess == true then
					env.info(("MOSSUpdateUnit found a unit part of a group to be excluded from update: " .. gName))
				end
				return
			end
			
			if not unit then
				if debugProcess == true then
					env.info(("MOSSUpdateUnit dont found unit: " .. object.unitId))
				end
				return
			end
			
			-- stop if it's airplane or helo.
			if keepAUPos and (kindID == "plane" or kindID =="helicopter") then
				return
			end

			unit["x"] = object.pos["x"];
			unit["y"] = object.pos["z"];

			if unitID == 1 then  -- try to fix ME stuff
				group["x"] = unit["x"];
				group["y"] = unit["y"];
				group.route.points[1]["x"] = unit["x"];
				group.route.points[1]["y"] = unit["y"];
			end
			if KeepGroupsRoutes == false or KeepGroupsRoutes == nil then
				for id, pointData in pairs (group.route.points) do
					if id > 1 then
						table.remove(group.route.points, id);
					end
				end
				if group.route.spans then
					group.route.spans = {}
				end
				
			end
		end
		
	end
	--]]--

	-- reset state variables to initial state
	function MOSSReset() -- OK
	  SaveProcedureInitDone = false;
	  gMOSSNextEventIdx = nil;
	  gMOSSEvents = {};
	  gMOSSFC = 5;          -- phase shift to avoid running in the same slmod frame

		if debugProcess == true then
			env.info(("--> MOSSReset() ha resettato le variabili e completato il processo" .. "\n"))	  -- Printa solo conferma che ha letto la variabile mission.
		end

	end
	--]]--

	--funzioni di start, run & stop
	function MOSSStartMission()  -- OK

		MOSSReset();

		--gMOSSLog:write("[DEBUG  ] Mission start\n");

		gMOSSMix = IntegratedGetUnzippedMission();

		if debugProcess == true and gMOSSMix ~= nil then
			env.info(("--> MOSSStartMission() ha creato gMOSSMix, che non è nil" .. "\n"))	  -- Printa solo conferma che ha letto la variabile mission.
		end

	  SaveProcedureInitDone = true;

	end
	--]]--	

	function DAWS.createStatics(mission) -- OK		
		if superDebugProcess == true then
			DAWS.dumpTable("tblDeadUnits.lua", tblDeadUnits)
		end	
		
		if debugProcess == true then
			env.info(("DAWS.createStatics launched"))		
		end
		
		for id, deadData in pairs (tblDeadUnits) do
			
			if debugProcess == true then
				env.info(("DAWS.createStatics found unit " .. tostring(deadData.staticTable.name) .. " to be inserted as static"))
			end	
			
			if deadData.objCategory ~= 6 then -- not cargos
			
				local correctCoalition = nil
				if deadData.coalitionID == 0 then
					correctCoalition = "neutral"
				elseif deadData.coalitionID == 1 then
					correctCoalition = "red"				
				elseif deadData.coalitionID == 2 then
					correctCoalition = "blue"				
				end			

				if debugProcess == true then
					env.info(("DAWS.createStatics coalition is " .. tostring(correctCoalition)))
				end	
				
				local correctCountry = nil
				for ctryID, ctryData in pairs (mission.coalition[correctCoalition]["country"]) do
					if deadData.countryID == ctryData.id then
						correctCountry = ctryID
					end
				end
				
				if debugProcess == true then
					env.info(("DAWS.createStatics country index is " .. tostring(correctCountry)))
				end	
				
				-- check static existence
				if not mission.coalition[correctCoalition]["country"][correctCountry]["static"] then
					mission.coalition[correctCoalition]["country"][correctCountry]["static"] = {}
					if debugProcess == true then
						env.info(("Static table not found, created static table"))
					end							
				end
				
				if debugProcess == true then
					env.info(("DAWS.createStatics Check A"))
				end	
				
				-- check group existence in static
				if not mission.coalition[correctCoalition]["country"][correctCountry]["static"]["group"] then
					mission.coalition[correctCoalition]["country"][correctCountry]["static"]["group"] = {}
					if debugProcess == true then
						env.info(("Group table not found, created static table"))
					end							
				end	

				if debugProcess == true then
					env.info(("DAWS.createStatics Check B"))
				end	
				
				local groupTable = mission.coalition[correctCoalition]["country"][correctCountry]["static"]["group"]


				if debugProcess == true then
					env.info(("DAWS.createStatics Check C"))
				end				

				groupTable[#groupTable + 1] = deadData.staticTable
				
			end
		end
		
	end

	
	--###########################################   CHILD CODE FOR MOSS   ######################################################
	
	--execute the savefile update.
	DAWS.startStateSaveup = function()
		MOSSStartMission()
	end
	--]]--	
	
	-- execute the "mission" file export!
	DAWS.doSaveFile = function(NewDictPath)
		MOSSSave(NewDictPath)
		--DebugPrint()
	end
	--]]--	
	
	--update the mission start time
	function DAWS.UpdateMissionStartTime()
	
		local CURstartDateDay			= env.mission["date"]["Day"]
		local CURstartDateYear			= env.mission["date"]["Year"]
		local CURstartDateMonth			= env.mission["date"]["Month"]	
		local CURstartTime				= env.mission["start_time"]
		local CURhours					= math.floor((env.mission["start_time"]/3600))
		local CURmin					= math.floor(((env.mission["start_time"] - (3600*CURhours)))/60)
		local CURsec					= 0 --env.mission["start_time"]-(3600*CURhours)-(60*CURmin)
		
		--local CURtime					= os.time{year=CURstartDateYear, month=CURstartDateMonth, day=CURstartDateDay, hour=CURhours, min=CURmin, sec=CURsec}
		local CURday					= os.time{year=CURstartDateYear, month=CURstartDateMonth, day=CURstartDateDay, hour=0}
		local CURtime					= CURday + env.mission["start_time"]
		
		if debugProcess == true then
			env.info(("the KeepContinousMission is " .. tostring(KeepContinousMission)))
			env.info(("the CURtime is " .. tostring(CURtime))) 
		end	
		
		-- ISTRO https://www.lua.org/pil/22.1.html
	
		if KeepContinousMission == true then		
			local NEWtime 				= CURday + timer.getAbsTime() -- CURtime --((math.floor((timer.getTime()/60))+1)*60)
			if debugProcess == true then
				env.info(("KeepContinousMission: the NEWtime is " .. tostring(NEWtime))) 	
			end				
			--local NEWtimeTable			= os.date("*t", NEWtime)			
			NEWstartDateYear			= tonumber(os.date("%Y", NEWtime))
			NEWstartDateMonth			= tonumber(os.date("%m", NEWtime))
			NEWstartDateDay				= tonumber(os.date("%d", NEWtime))
			--local zeroTime				= tonumber(os.time{year=1970, month=1, day=1, hour=0, sec=1})
			local NEWstartTimeZero		= tonumber(os.time{year=NEWstartDateYear, month=NEWstartDateMonth, day=NEWstartDateDay, hour=0}) -- + zeroTime
			if debugProcess == true then
				env.info(("the zeroTime is " .. tostring(zeroTime))) 
				env.info(("the NEWstartDateYear is " .. tostring(NEWstartDateYear))) 
				env.info(("the NEWstartDateMonth is " .. tostring(NEWstartDateMonth))) 
				env.info(("the NEWstartDateDay is " .. tostring(NEWstartDateDay))) 
				env.info(("the NEWstartTimeZero is " .. tostring(NEWstartTimeZero))) 	
			end				
			NEWstartTime				= NEWtime - NEWstartTimeZero
			if debugProcess == true then
				env.info(("the NEWstartTime is " .. tostring(NEWstartTime))) 	
			end	
			
		elseif UpdateSceneryDate == true then -- current date + 1
			local RandomTime			= math.random(8,21)*60*60 + 24*60*60
			local NEWtime 				= CURday + RandomTime
			if debugProcess == true then
				env.info(("UpdateSceneryDate: the NEWtime is " .. tostring(NEWtime))) 	
			end	
			local NEWtimeTable			= os.date("*t", NEWtime)			
			NEWstartDateYear			= tonumber(os.date("%Y", NEWtime))
			NEWstartDateMonth			= tonumber(os.date("%m", NEWtime))
			NEWstartDateDay				= tonumber(os.date("%d", NEWtime))
			NEWstartTime				= RandomTime
			
		else -- no date updade		
			NEWstartDateYear			= CURstartDateYear
			NEWstartDateMonth			= CURstartDateMonth
			NEWstartDateDay				= CURstartDateDay
			NEWstartTime				= CURstartTime
		
		end
	end
	--]]--	
	
	-- save a new mission file
	DAWS.buildNewMizFile = function()
		
		-- setting variable (should became much more campaign-related the naming of the Miz-files
		if theAutosaveFilename == nil then
			saveCounter = saveCounter + 1
		end
	

		-- check retrievable max time files
		local allowSave = true
		
		if allowSave == true then
			
			--local OldMizPath = nil
			--OldMizPath = loadedMissionPath
			
			if debugProcess == true then
				env.info(("the loadedMissionPath is " .. tostring(loadedMissionPath))) 	
			end			
			
			local NewMizPath = FixedPath or theAutosaveFilename or missionfilesdirectory .. "DAWS-SavedMission_" .. saveCounter .. ".miz" -- change to writedir
			local NewMizTempDir = "DAWS_TempMix/"
			lfs.mkdir(missionfilesdirectory .. "Temp/" .. NewMizTempDir)
			local OldMissionPath = missionfilesdirectory .. "Temp/" .. "mission"
			local NewMissionPath = missionfilesdirectory .. "Temp/" .. NewMizTempDir .. "mission"
			local OldDictPath = missionfilesdirectory .. "Temp/".."dictionary"
			local NewDictPath = missionfilesdirectory .. "Temp/" .. NewMizTempDir .."l10n/" .. "DEFAULT/" .. "dictionary"

			-- external module files path
			local OldEAfilesPath = missionfilesdirectory .. "Temp/" .. "DAWS_mountedInfantryTable_SM"
			local NewEAfilesPath = missionfilesdirectory .. "Temp/" .. NewMizTempDir  .."Scripts/" .. "DAWS_mountedInfantryTable_SM"		


			
			--## METHOD 3 unpack, overwrite, repack
			local zipFile, err = minizip.unzOpen(loadedMissionPath, 'rb')
			zipFile:unzGoToFirstFile() --vai al primo file dello zip		
			
			-- unpack
			local NewSaveresourceFiles = {}
			local CreatedDirectories = {}
			local function Unpack()
				while true do --scompattalo e passa al prossimo
					local filename = zipFile:unzGetCurrentFileName()
					local fullPath = missionfilesdirectory .. "Temp/" .. NewMizTempDir .. filename
					if debugProcess == true then
						env.info(("file ".. tostring(filename) .. " will be extracted.")) 
					end
					
					--create subdirectories
					local subdir1_string = nil
					local subdir2_string = nil
					local subdir3_string = nil
					local subdir1_end = nil
					local subdir2_end = nil
					local subdir3_end = nil
					local subdir1 = nil
					local subdir2 = nil
					local subdir3 = nil
					local BaseTempDir = missionfilesdirectory .. "Temp/" .. NewMizTempDir
					-- check if a subdir exist
					subdir1_string = string.sub(filename, 1)
					
					-- identify first subdir string
					if subdir1_string then
						subdir1_end = string.find(subdir1_string, "/")
						if subdir1_end then
							subdir1 = string.sub(subdir1_string, 1, subdir1_end-1)
							if debugProcess == true then
								env.info(("creating subdir1 ".. tostring(subdir1))) 
							end							
							lfs.mkdir(BaseTempDir .. subdir1 .. "/")
							CreatedDirectories[#CreatedDirectories + 1] = BaseTempDir .. subdir1 .. "/"
							BaseTempDir = BaseTempDir .. subdir1 .. "/"
							if debugProcess == true then
								env.info(("created subdir1")) 
							end								
							subdir2_string = string.sub(subdir1_string, subdir1_end+1)
						end	
					end
					
					-- identify second subdir string
					if subdir2_string then
						subdir2_end = string.find(subdir2_string, "/")
						if subdir2_end then
							subdir2 = string.sub(subdir2_string, 1, subdir2_end-1)
							if debugProcess == true then
								env.info(("creating subdir2 ".. tostring(subdir2))) 
							end							
							lfs.mkdir(BaseTempDir .. subdir2 .. "/")
							CreatedDirectories[#CreatedDirectories + 1] = BaseTempDir .. subdir2 .. "/"
							BaseTempDir = BaseTempDir .. subdir2 .. "/"
							if debugProcess == true then
								env.info(("created subdir2")) 
							end								
							subdir3_string = string.sub(subdir2_string, subdir2_end+1)
						end	
					end				
					
					-- identify third subdir string
					if subdir3_string then
						subdir3_end = string.find(subdir3_string, "/")
						if subdir3_end then
							subdir3 = string.sub(subdir3_string, 1, subdir3_end-1)
							if debugProcess == true then
								env.info(("creating subdir3 ".. tostring(subdir3))) 
							end							
							lfs.mkdir(BaseTempDir .. subdir3 .. "/")
							CreatedDirectories[#CreatedDirectories + 1] = BaseTempDir .. subdir3 .. "/"
							BaseTempDir = BaseTempDir .. subdir3 .. "/"
							if debugProcess == true then
								env.info(("created subdir3")) 
							end								
							subdir4_string = string.sub(subdir3_string, subdir3_end+1)
						end	
					end							

					-- identify fourth and last subdir string
					if subdir4_string then
						subdir4_end = string.find(subdir4_string, "/")
						if subdir4_end then
							subdir4 = string.sub(subdir4_string, 1, subdir4_end-1)
							if debugProcess == true then
								env.info(("creating subdir4 ".. tostring(subdir4))) 
							end							
							lfs.mkdir(BaseTempDir .. subdir4 .. "/")
							CreatedDirectories[#CreatedDirectories + 1] = BaseTempDir .. subdir4 .. "/"
							BaseTempDir = BaseTempDir .. subdir4 .. "/"
							if debugProcess == true then
								env.info(("created subdir4")) 
							end								
			
						end	
					end
					
					zipFile:unzUnpackCurrentFile(fullPath) 
					NewSaveresourceFiles[filename] = fullPath
					if not zipFile:unzGoToNextFile() then 
						break
					end
				end
				return NewSaveresourceFiles
			end
			Unpack() -- execute the unpacking
			
			-- inserted Save exec here
			DAWS.doSaveFile(NewDictPath)
			-- modified mission files copy
			DAWS.moveFile(OldMissionPath, NewMissionPath) -- overwrite existing "mission" table
			if debugProcess == true then
				env.info(("mission file moved")) 	
			end		
			DAWS.moveFile(OldDictPath, NewDictPath)			
			if debugProcess == true then
				env.info(("dictionary file moved")) 	
			end
			
			-- MADE IT DYNAMIC
			-- external module files copy
			if EA_infantry_carrier and DAWS_mountedInfantryTable_SM and table.getn(DAWS_mountedInfantryTable_SM) > 0 then
				local fileIsThere = DAWS.fileExist(OldEAfilesPath)
				if fileIsThere == true then				
					DAWS.moveFile(OldEAfilesPath, NewEAfilesPath)
					local filename = "Scripts/DAWS_mountedInfantryTable_SM"
					NewSaveresourceFiles[filename] = NewEAfilesPath
					if debugProcess == true then
						env.info(("infantry carrier table file moved")) 	
					end
				end
			end
			
			if superDebugProcess == true then
				DAWS.dumpTable("NewSaveresourceFiles.lua",NewSaveresourceFiles)
			end
			
			-- pack everything
			local miz = minizip.zipCreate(NewMizPath)
			local function packMissionResources(miz)
				for file, fullPath in pairs(NewSaveresourceFiles) do
					local fileIsThere = DAWS.fileExist(fullPath)
					if fileIsThere == true then
						miz:zipAddFile(file, fullPath)					
					end
					os.remove(fullPath)
				end
			end
			packMissionResources(miz)
			
			-- close zip file
			miz:zipClose()
			
			-- remove directories
			for id, path in pairs(CreatedDirectories) do
				if debugProcess == true then
					env.info(("removing dir: " .. tostring(path))) 	
				end			
				lfs.rmdir(path)
			end
			lfs.rmdir(missionfilesdirectory .. "Temp/" .. NewMizTempDir  .. "Scripts/")
			lfs.rmdir(missionfilesdirectory .. "Temp/" .. NewMizTempDir)
			lfs.rmdir(missionfilesdirectory .. "Temp/")
			
			zipFile:unzClose()
			
			-- print ok message
			if theMessageState == true then
				trigger.action.outText("... scenery saved: " .. NewMizPath, 10 )
			end	
			
		end
	end
	--]]--	

	-- on call: call in a radio item that execute once the update & saving procedures.
	DAWS.oncallworkflow = function()
		if debugProcess == true then
			env.info(("DAWS is saving the mission... "))
		end
		DAWS.checkLastLoadedMission()
		if theMessageState == true then
			trigger.action.outText("DAWS is saving the scenery... ", 10 )
		end
		--DAWS.doSaveFile()
		if UseFixedPath == true then
			FixedPath = FixedSavePath
		else 
			FixedPath = nil
		end
		DAWS.buildNewMizFile()
		if debugProcess == true then
			env.info(("... mission saved" ))
		end
	end
	--]]--
	
	-- initialize radio menù
	DAWS.CreateRadioMenu = function()
		if RadioMenuSingleGroup == true then
			local timerizeradio = function()
		
				if debugProcess == true then
					env.info(("RadioMenuSingleGroup is true"))
				end			
				local groupSaver = Group.getByName("DAWS_Saver")
				if groupSaver then
					if debugProcess == true then
						env.info(("groupSaver exist"))
					end				
					local groupSaverID = groupSaver:getID()
					if groupSaverID then
						if debugProcess == true then
							env.info(("groupSaverID exist"))
						end					
						missionCommands.addCommandForGroup(groupSaverID, "DAWS - Save scenery", nil, DAWS.oncallworkflow)
						if debugProcess == true then
							env.info(("missionCommands created"))
						end		
					end
				else
					local unitSaver = Unit.getByName("DAWS_Saver")				
					if unitSaver then
						if debugProcess == true then
							env.info(("unitSaver exist"))
						end	
						local groupSaver = unitSaver:getGroup()
						if debugProcess == true then
							env.info(("groupSaver by unit exist"))
						end							
						local groupSaverID = groupSaver:getID()
						if groupSaverID then
							if debugProcess == true then
								env.info(("groupSaverID by unit exist"))
							end					
							missionCommands.addCommandForGroup(groupSaverID, "DAWS - Save scenery", nil, DAWS.oncallworkflow)
							if debugProcess == true then
								env.info(("missionCommands created"))
							end		
						end				
					end
				end
			end
			timer.scheduleFunction(timerizeradio, {}, timer.getTime() + 5)
		else
			missionCommands.addCommand("DAWS - Save scenery", nil, DAWS.oncallworkflow)
		end
		
	end
	--]]--

	DAWS.copyFile =  function(old, new)
		local i = io.open(old, "r")
		local o = io.open(new, "w")
		if i then
			o:write(i:read("*a"))
			o:close()
			i:close()
		end		
	end
	--]]--

	DAWS.moveFile = function(old, new)
	   DAWS.copyFile(old, new)
	   os.remove(old)
	end
	--]]--

	DAWS.autosaveCycle = function()
		local tempMessageState = theMessageState
		timer.scheduleFunction(DAWS.autosaveCycle, {}, timer.getTime() + 600)

		--DAWS.checkLastLoadedMission()
		theMessageState = false 
		theAutosaveFilename = missionfilesdirectory .. "DAWS_AutoSave_temp.miz"  -- .. theAutosaveFilename_num .. ".miz"
		--theAutosaveFilename = string.sub(loadedMissionPath, 1, -5) .. "_autosave.miz"
		
		env.info("DAWS is autosaving... " .. theAutosaveFilename)
		
		DAWS.oncallworkflow()
		
		-- added to grant external access
		env.info("DAWS is copying file... ")
		DAWS.copyFile(theAutosaveFilename, missionfilesdirectory .. AutoSaveFileName)
		os.remove(theAutosaveFilename)
		env.info("DAWS file copied. ")
		
		theAutosaveFilename = nil
		--theAutosaveFilename_num = theAutosaveFilename_num + 1
		theMessageState = tempMessageState
	end
	--]]--
	
	DAWS.checkLastLoadedMission = function()
		--os.execute("xcopy " .. lfs.writedir() .. "Logs/dcs.log.old " .. lfs.writedir() .. "Logs/dcsDAWS.log")
		--os.execute("cmd /c " .. lfs.writedir() .. "Logs/dcs.log " .. lfs.writedir() .. "Logs/dcsDAWS.log")
		local logpath = lfs.writedir() .. "Logs/mixpath.txt"
		--lfs.writedir() .. "AMVI/SaveMission/mixpath.txt"  --lfs.writedir() .. "Logs/dcs.log.old"
		local i = io.open(logpath, "r")
		for line in io.lines(i) do
			local text = line:match("(.-)$")
			if text == nil then
				env.info(("DAWS can't access last mission path"))
			else
				loadedMissionPath = text
				env.info(("DAWS is using this path: " .. loadedMissionPath))
			end
		end
		i:close()
		
		if LoadInternalFiles == true then
			LoadInternalFiles = false
			local tempPath = missionfilesdirectory .. "DAWS_tempFile.miz"
			
			DAWS.copyFile(loadedMissionPath, tempPath)
			
			local zipFile, err = minizip.unzOpen(tempPath, 'rb')
			zipFile:unzGoToFirstFile() --vai al primo file dello zip				
			
			-- loadDAWSfiles
			local function loadDAWSfiles()
				while true do --scompattalo e passa al prossimo
					local filename = zipFile:unzGetCurrentFileName()

					if debugProcess == true then
						env.info(("evaluating file ".. tostring(filename)))
					end
					if string.find(filename, "DAWS") then
						local fullPath = missionfilesdirectory .. string.sub(filename, string.find(filename, "DAWS"))
						if debugProcess == true then
							env.info(("found DAWS file: ".. tostring(string.sub(filename, string.find(filename, "DAWS"))))) 
						end							
						zipFile:unzUnpackCurrentFile(fullPath)
						if debugProcess == true then
							env.info(("file ".. tostring(string.sub(filename, string.find(filename, "DAWS"))) .. " will be readed and loaded.")) 
						end								
						
						local i = io.open(fullPath, "r")
						table_i = i:read('*all')
						tmp_table_i = loadstring(table_i)
						tmp_table_i()
						if superDebugProcess == true then
							DAWS.dumpTable("DAWS_mountedInfantryTable_SM_init.lua", DAWS_mountedInfantryTable_SM)									
						end
						i:close()
						
						os.remove(fullPath)
					end
					
					if not zipFile:unzGoToNextFile() then 
						break
					end
				end
				zipFile:unzClose()
			end
			loadDAWSfiles() -- execute the unpacking			
			
			os.remove(tempPath)
			
		end
	end
	--]]--

	--##### EXEC
	
	-- initialise save process
	DAWS.startStateSaveup()
	if RadioMenuVariable == true then
		DAWS.CreateRadioMenu()
	end
	--]]--
	
	-- timed autosave function
	if AutoSaveEnable == true then
		--mist.scheduleFunction(DAWS.autosaveCycle,{},timer.getTime() + 120,(60*5),(MaxTimeFileCheckHours*3600-600))
		timer.scheduleFunction(DAWS.autosaveCycle, {}, timer.getTime() + 120)
	end
	--]]--
	
	--##### MAP OBJECT
	
	if MapObjectPersitence == true then
	
		PSSS = {}

		local tss = ";"
		DeadMapObjects = {}
		DeadObjCode = env.getValueDictByKey(env.mission.sortie)
		local ExplosionPower = 200 -- this is the explosion power. Small explosion may not be sufficient to destroy the building, else a big explosion may destroy the nearby building also.
		local destroyMethod = 1 -- 0 means by destroy, 1 by explosion. 0 does not work due to a scripting engine bug.

		local PSSStools = {}
		PSSStools.io = io
		PSSStools.lfs = lfs
		--DAWStools.fs = fs
		PSSStools.os = os
		PSSStools.zip = minizip
		
		 -- this function store in a file the destroyed map objects table
		 PSSS.deadMapObjCollect = function() 
		  local deadOBJ = "" 
		  -- add to the previous data stored in "deadOBJ" string the new data
		  for deadId,deadData in pairs(mist.DBs.deadObjects) do
		   if deadData.objectType == "building" then -- filter map Objects
			local Id = deadId
			local Pos = deadData.objectPos
			deadOBJ = deadOBJ .. Id.. tss .. DeadObjCode .. tss .. Pos.x .. tss  .. Pos.y .. tss  .. Pos.z .. "\n"
		   end
		  end 
		  -- now overwrite the old file (erase previous data)
		  local o = PSSStools.io.open(moddirectory .. DeadObjCode .. "_deadobjects.csv", "w") 
		  o:write(deadOBJ)
		  o:close()
		 end		

		 
		 -- this function will destroy objects indicated in the 
		 PSSS.deadMapObjDestroy = function()
		  
		  -- retrieve dead objects data
		  
		  local u = PSSStools.io.open(moddirectory .. DeadObjCode .. "_deadobjects.csv", "r")  
		  
		  for line in PSSStools.io.lines(u) do
		   local rdeadID, rdeadCode, rdeadPosX, rdeadPosY, rdeadPosZ = line:match("(%d-)"..tss.."(.-)"..tss.."(.-)"..tss.."(.-)"..tss.."(.-)$")
			if (rdeadID) then 
			DeadMapObjects[#DeadMapObjects + 1] = { deadID = rdeadID, deadCode = rdeadCode, deadPosX = rdeadPosX, deadPosY = rdeadPosY, deadPosZ = rdeadPosZ}
		   end
		  end
		  u:close()  
		  
		  
		  -- exec the deletion
		  for id, DeadData in pairs(DeadMapObjects) do
			if DeadObjCode == DeadData.deadCode then
			   local deadX = tonumber(DeadData.deadPosX)
			   local deadY = tonumber(DeadData.deadPosY)
			   local deadZ = tonumber(DeadData.deadPosZ)
			  
			   local ExpPos = {
				   x = deadX,
				   y = deadY,
				   z = deadZ
				   }
				   
			   local volume =  {
				   id = world.VolumeType.SPHERE,
				   params = {
					  point = ExpPos,
					  radius = 0.2
					 }
				   }   
			  
			   local function handler(object, data)
				Object.destroy(object)
			   end  
			  
			   if destroyMethod == 0 then -- does not work due to scripting bug.
				if ExpPos then
				 world.searchObjects(Object.Category.SCENERY, volume, handler, nil)
				end
			   elseif destroyMethod == 1 then
				if id then
				 trigger.action.explosion(ExpPos, ExplosionPower)
				end
			   end
			  end
			end
		 end		 
		 
		 -- run code
		 if DeadObjCode then
			timer.scheduleFunction(PSSS.deadMapObjDestroy,{},timer.getTime() + 2) -- re-destroy the previously destroyed building once code is loaded
			PSSS.repeater = function() -- was local
				timer.scheduleFunction(PSSS.deadMapObjCollect,{},timer.getTime() + 59)
				timer.scheduleFunction(PSSS.repeater,{},timer.getTime() + 60)
			end
			timer.scheduleFunction(PSSS.deadMapObjCollect,{},timer.getTime() + 3)
			PSSS.repeater()
			--mist.scheduleFunction(PSSS.deadMapObjCollect,{},timer.getTime() + 3, 60, (4*60*60)) -- since you get into the 6th minute of mission, every minute the function will update the destroyed building log file, till missiong get at 4 hour run (you may change parameters if you want)
			env.info("Found DeadObjCode variable. Value: " .. tostring(DeadObjCode))
		 else
			env.info("no global DeadObjCode found")
		 end		 
		 
	end
	--]]--
	
	-- load this to get loaded the internal files
	DAWS.checkLastLoadedMission()
	
	DAWS.deathRecorder = {}
	function DAWS.deathRecorder:onEvent(event)
		if event.id == world.event.S_EVENT_DEAD then
			
			if debugProcess == true then
				env.info(("--> DAWS deathRecorder : dead event has been detected with a unit"))
			end  
		
			--dead
			local unitName		 	= nil
			local unitTable			= nil
			local unitPos			= nil
			local unitCategory		= nil
			local unitCoalition		= nil
			local unitCountry		= nil
			local unitTypeName		= nil
			
			local groupTable 	= {}
			if event.initiator then
				unitName 			= event.initiator:getName()
				unitTable 			= Unit.getByName(unitName)
				if unitTable then
					unitPos 		= unitTable:getPosition().p
					unitCategory 	= unitTable:getDesc().category
					unitCatEnum		= unitTable:getCategory()
					unitCoalition 	= unitTable:getCoalition()
					unitCountry 	= unitTable:getCountry()
					unitTypeName	= unitTable:getTypeName()
				end
			end			
			
			if debugProcess == true then
				env.info(("--> DAWS deathRecorder : unit name:" .. tostring(unitName) .. ", category:" .. tostring(unitCategory) .. ", country:" .. tostring(unitCountry)))
			end 
			
			if unitName and unitTable and unitCategory and unitCategory ~= 3 then
				StaticStartNumber = StaticStartNumber +1
			
				local HiddenSet = false
				if HiddenStatics == true then
					HiddenSet = true
				end			
				
				local correctCategory = nil
				if unitCategory == 0 then
					correctCategory = "Planes"
				elseif unitCategory == 1 then
					correctCategory = "Helicopters"				
				elseif unitCategory == 2 then
					correctCategory = "Unarmed"
				elseif unitCategory == 4 then
					correctCategory = "Fortifications"				
				end
				--]]--

				
				groupTable = {
												["heading"] = 0,
												["route"] = 
												{
													["points"] = 
													{
														[1] = 
														{
															["alt"] = unitPos.y,
															["type"] = "",
															["name"] = "",
															["y"] = unitPos.z,
															["speed"] = 0,
															["x"] = unitPos.x,
															["formation_template"] = "",
															["action"] = "",
														}, -- end of [1]
													}, -- end of ["points"]
												}, -- end of ["route"]
												["groupId"] = baseGcounter + 1,
												["hidden"] = HiddenSet,
												["units"] = 
												{
													[1] = 
													{
														["type"] = unitTypeName,
														["unitId"] = baseGcounter + 1,
														["livery_id"] = "autumn",
														["rate"] = 20,
														["y"] = unitPos.z,
														["x"] = unitPos.x,
														["name"] = "CreatedStatic " .. tostring(StaticStartNumber),
														["category"] = correctCategory,
														["canCargo"] = false,
														["heading"] = 0,
													}, -- end of [1]
												}, -- end of ["units"]
												["y"] = unitPos.z,
												["x"] = unitPos.x,
												["name"] = unitName,
												["dead"] = true,
											} -- end of [1]				
				baseGcounter = baseGcounter +1
			
				tblDeadUnits[#tblDeadUnits + 1] = {coalitionID = unitCoalition, countryID = unitCountry, staticTable = groupTable, objCategory = unitCatEnum}

				if debugProcess == true then
					env.info(("--> DAWS deathRecorder : unit name:" .. tostring(unitName) .. "added to tblDeadUnits" .. tostring(unitCountry)))
				end 
				
			end
			
	
		end	
		
	end
	world.addEventHandler(DAWS.deathRecorder)

	
	
	env.info(("DAWS Save Mission version: " .. MainVersion .. "." .. SubVersion .. "." .. Build .. " loaded"))

	-- ~=
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	