--***********************************************************
--**                    THE INDIE STONE                    **
--***********************************************************

require "ISUI/ISScrollingListBox"

MapSpawnSelect = ISPanelJoypad:derive("MapSpawnSelect")

local FONT_HGT_SMALL = getTextManager():getFontHeight(UIFont.Small)
local FONT_HGT_MEDIUM = getTextManager():getFontHeight(UIFont.Medium)

MapSpawnSelectListBox = ISScrollingListBox:derive("MapSpawnSelectListBox")

function MapSpawnSelectListBox:render()
	ISScrollingListBox.render(self)
--	self:drawRectBorder(self.listbox:getX(), self.listbox:getY(), self.listbox:getWidth(), self.listbox:getHeight(), 0.9, 0.4, 0.4, 0.4)
	if self.joyfocus then
		self:drawRectBorder(0, -self:getYScroll(), self:getWidth(), self:getHeight(), 0.4, 0.2, 1.0, 1.0);
		self:drawRectBorder(1, 1-self:getYScroll(), self:getWidth()-2, self:getHeight()-2, 0.4, 0.2, 1.0, 1.0);
	end
end

function MapSpawnSelectListBox:onJoypadDirUp(joypadData)
	if self.selected == 1 and self.parent.textEntry and self.parent.textEntry:isVisible() then
		self.parent.textEntry:focus()
		joypadData.focus = self.parent.textEntry
		updateJoypadFocus(joypadData)
		return
	end
	ISScrollingListBox.onJoypadDirUp(self, joypadData)
end

function MapSpawnSelectListBox:onJoypadDirRight(joypadData)
	joypadData.focus = self.parent.richText
	updateJoypadFocus(joypadData)
end

function MapSpawnSelectListBox:onJoypadBeforeDeactivate(joypadData)
	self.parent:onJoypadBeforeDeactivate(joypadData)
end

-----

MapSpawnSelectInfoPanel = ISRichTextPanel:derive("MapSpawnSelectInfoPanel")

function MapSpawnSelectInfoPanel:prerender()
	self:doRightJoystickScrolling(10, 10)
	ISRichTextPanel.prerender(self)
end

function MapSpawnSelectInfoPanel:render()
	ISRichTextPanel.render(self)
	if self.joyfocus then
		self:drawRectBorder(0, -self:getYScroll(), self:getWidth(), self:getHeight(), 0.4, 0.2, 1.0, 1.0);
		self:drawRectBorder(1, 1-self:getYScroll(), self:getWidth()-2, self:getHeight()-2, 0.4, 0.2, 1.0, 1.0);
	end
end

MapSpawnSelectInfoPanel.doRightJoystickScrolling = ISPanelJoypad.doRightJoystickScrolling

function MapSpawnSelectInfoPanel:onJoypadDown(button, joypadData)
	if button == Joypad.AButton then
		self.parent.nextButton:forceClick()
	end
	if button == Joypad.BButton then
		self.parent.backButton:forceClick()
	end
end

function MapSpawnSelectInfoPanel:onJoypadDirUp(joypadData)
	self:setYScroll(self:getYScroll() + 48)
end

function MapSpawnSelectInfoPanel:onJoypadDirDown(joypadData)
	self:setYScroll(self:getYScroll() - 48)
end

function MapSpawnSelectInfoPanel:onJoypadDirLeft(joypadData)
	self:setYScroll(0)
	joypadData.focus = self.parent.listbox
	updateJoypadFocus(joypadData)
end

function MapSpawnSelectInfoPanel:onJoypadBeforeDeactivate(joypadData)
	self.parent:onJoypadBeforeDeactivate(joypadData)
end

-----

function MapSpawnSelect:initialise()
	ISPanelJoypad.initialise(self)
end

function MapSpawnSelect:getFixedSpawnRegion()
	if not isClient() then return nil end
	local spawnPoint = getServerOptions():getOption("SpawnPoint")
	if not spawnPoint or #spawnPoint:split(",") ~= 3 then
		return nil
    end
	local xyz = spawnPoint:split(",")
	local x = tonumber(xyz[1])
	local y = tonumber(xyz[2])
	local z = tonumber(xyz[3])
	if x and y and z and (x ~= 0 or y ~= 0) then
		local worldX = math.floor(x / 300)
		local worldY = math.floor(y / 300)
		local posX = x - worldX * 300
		local posY = y - worldY * 300
		return { {
			name = getText("UI_mapspawn_ServerSpawnPoint"), points = {
				unemployed = {
					{ worldX = worldX, worldY = worldY, posX = posX, posY = posY, posZ = z },
				},
			}
		} }
	end
	return nil
end

function MapSpawnSelect:getSafehouseSpawnRegion()
	if not isClient() then return nil end
	if not getServerOptions():getBoolean("SafehouseAllowRespawn") then return nil end
	local username = getClientUsername()
	if MainScreen.instance.inGame then
		if CoopCharacterCreation.instance.playerIndex > 0 then
			username = CoopUserName.instance:getUserName()
		end
	end
	for i=0,SafeHouse.getSafehouseList():size()-1 do
		local safe = SafeHouse.getSafehouseList():get(i);
		if safe:isRespawnInSafehouse(username) and (safe:getPlayers():contains(username) or (safe:getOwner() == username)) then
			x = safe:getX() + (safe:getH() / 2);
			y = safe:getY() + (safe:getW() / 2);
			z = 0;
			local worldX = math.floor(x / 300)
			local worldY = math.floor(y / 300)
			local posX = x - worldX * 300
			local posY = y - worldY * 300
			return { {
				name = getText("UI_mapspawn_Safehouse"), points = {
					unemployed = {
						{ worldX = worldX, worldY = worldY, posX = posX, posY = posY, posZ = z },
					},
				}
			} }
		end
	end
	return nil
end

function MapSpawnSelect:getChallengeSpawnRegion()
	if not getCore():isChallenge() then return nil end
	return LastStandData.getSpawnRegion()
end

function MapSpawnSelect:getSpawnRegions()
	return self:getSafehouseSpawnRegion() or self:getFixedSpawnRegion() or self:getChallengeSpawnRegion() or SpawnRegionMgr.getSpawnRegions()
end

function MapSpawnSelect:hasChoices()
	local regions = self:getSpawnRegions()
	return regions and #regions > 1
end

function MapSpawnSelect:useDefaultSpawnRegion()
	self.selectedRegion = nil
	local regions = self:getSpawnRegions()
	if not regions or #regions == 0 then return end
	self.selectedRegion = regions[1]
	return self.selectedRegion
end

function MapSpawnSelect:fillList()
	self.listbox:clear()
	local regions = self:getSpawnRegions()
	if not regions then return end
	for _,v in ipairs(regions) do
		local info = getMapInfo(v.name)
		if info then
			local item = {};
			item.name = info.title or "NO TITLE";
			item.region = v;
			item.dir = v.name;
			item.desc = info.description or "NO DESCRIPTION";
			item.worldimage = info.thumb;
			self.listbox:addItem(item.name, item);
		else
			local item = {}
			item.name = v.name;
			item.region = v;
			item.dir = "";
			item.desc = "";
			item.worldimage = nil;
			self.listbox:addItem(item.name, item);
		end
	end
	self.listbox:sort()

	self:hideOrShowSaveName()
end

function MapSpawnSelect:hideOrShowSaveName()
	-- There is no "Save Name" field when creating a co-op player
	if MainScreen.instance.inGame then return end

	-- When loading an existing save, don't display "Save Name" field
	if MainScreen.instance.createWorld and not getCore():isChallenge() then
		self.startY = 110
		self.textEntryLabel:setVisible(true)
		self.textEntry:setVisible(true)
	else
		self.startY = 80
		self.textEntryLabel:setVisible(false)
		self.textEntry:setVisible(false)
	end

	self.listbox:setY(self.startY)
	self.listbox:setHeight(self.height-30-30-self.startY)
end

function MapSpawnSelect:onOptionMouseDown(button, x, y)
	self:setVisible(false)
	if button.internal == "BACK" then
		self:clickBack()
	elseif button.internal == "NEXT" then
		self:clickNext()
	end
end

function MapSpawnSelect:onDblClick()
	self.nextButton:forceClick()
end

function MapSpawnSelect:clickBack()
	if getWorld():getGameMode() == "Multiplayer" then
		backToSinglePlayer()
		getCore():ResetLua("default", "exitJoinServer")
	elseif self.previousScreen == "LastStandPlayerSelect" then
		self.previousScreen = nil
		LastStandPlayerSelect.instance:setVisible(true, self.joyfocus)
	elseif self.previousScreen == "LoadGameScreen" then
		MainScreen.resetLuaIfNeeded()
		self.previousScreen = nil
		LoadGameScreen.instance:setSaveGamesList()
		MainScreen.instance.loadScreen:setVisible(true, self.joyfocus)
	elseif self.previousScreen == "NewGameScreen" then
		self.previousScreen = nil
		MainScreen.instance.soloScreen:setVisible(true, self.joyfocus)
	elseif self.previousScreen == "WorldSelect" then
		self.previousScreen = nil
		MainScreen.instance.worldSelect:setVisible(true, self.joyfocus)
	end
end

function MapSpawnSelect:clickNext()
	self.selectedRegion = self.listbox.items[self.listbox.selected].item.region
	self:setVisible(false)
	if MainScreen.instance.createWorld then
		getWorld():setWorld(sanitizeWorldName(self.textEntry:getText()));
	end
	if getWorld():getGameMode() == "Sandbox" and not checkSaveFileExists("map_sand.bin") then
		MainScreen.instance.sandOptions.previousScreen = "MapSpawnSelect";
		MainScreen.instance.sandOptions:setVisible(true, self.joyfocus)
	else
		MainScreen.instance.charCreationProfession.previousScreen = "MapSpawnSelect";
		MainScreen.instance.charCreationProfession:setVisible(true, self.joyfocus)
	end
end

function MapSpawnSelect:prerender()
	ISPanelJoypad.prerender(self)
	local enable = true
	if self.textEntry and self.textEntry:isVisible() then
		local rawText = self.textEntry:getText()
		local worldName = sanitizeWorldName(rawText)
		if worldName == "" or worldName ~= rawText or luautils.stringStarts(worldName, ".") or luautils.stringEnds(worldName, ".") then
			enable = false
		else
			local checkExistName = getWorld():getGameMode() .. getFileSeparator() .. worldName
			if checkExistName ~= self.checkExistsName then
				self.checkExistsName = checkExistName
				self.checkExist = checkSaveFolderExists(checkExistName)
			end
			if self.checkExist then
				enable = false
			end
		end
	end
	local focusOnEntry = false
	if self.textEntry then
		self.textEntry:setValid(enable)
		if self.textEntry.joyfocus then
			focusOnEntry = true
		end
	end
	self.nextButton:setEnable(enable)
	if self.ISButtonA and focusOnEntry then
		self.ISButtonA = nil
		self.nextButton:clearJoypadButton()
	elseif not self.ISButtonA and not focusOnEntry and self.joyfocus then
		self:setISButtonForA(self.nextButton)
	end
end

function MapSpawnSelect:render()
	ISPanelJoypad.render(self)
	self:drawTextCentre(getText("UI_mapspawn_title"), self.width / 2, 10, 1, 1, 1, 1, UIFont.Title)
	
	local selectedItem = self.listbox.items[self.listbox.selected].item;
	
	local thumbHeight = 0;
	local thumbPadY = 0;
	if selectedItem.worldimage ~= nil then
		thumbHeight = selectedItem.worldimage:getHeight();
		thumbPadY = 10;
		local BreakPoint = ((self.width/4)*3) - selectedItem.worldimage:getHeight()/2;
		self:drawTexture(selectedItem.worldimage, BreakPoint, self.startY, 1, 1, 1, 1);
		self:drawRectBorder( BreakPoint, self.startY, selectedItem.worldimage:getWidth(), selectedItem.worldimage:getHeight(), 0.3, 1, 1, 1);
		--        self:drawTexture(item.worldimage, MapSelecter.padXY, y+MapSelecter.padXY, 1, 1, 1, 1);
	end
	local descRectWidth = self.width - 17 - (self.width/2 + 30)
	local descRectHeight = self.height - 60 - (self.startY + thumbHeight + thumbPadY)
	self.richText:setX(self.width/2 + 30)
	self.richText:setY(self.startY + thumbHeight + thumbPadY)
	self.richText:setWidth(descRectWidth)
	self.richText:setHeight(descRectHeight)
	self.richText:setVisible(true);
	self.richText.text = selectedItem.desc or "";
	self.richText:paginate();
	self:drawRectBorder( self.richText.x, self.richText.y, self.richText:getWidth(), self.richText:getHeight(), 0.3, 1, 1, 1);
end

function MapSpawnSelect:doDrawItem(y, item, alt)
	local isMouseOver = self.mouseoverselected == item.index and not self:isMouseOverScrollBar()
	if self.selected == item.index then
		self:drawRect(0, (y), self:getWidth(), item.height-1, 0.3, 0.7, 0.35, 0.15)
	elseif isMouseOver then
		self:drawRect(1, y + 1, self:getWidth() - 2, item.height - 2, 0.95, 0.05, 0.05, 0.05);
	end
	self:drawRectBorder(0, (y), self:getWidth(), item.height, 0.5, self.borderColor.r, self.borderColor.g, self.borderColor.b)
	local fontHgt = getTextManager():getFontFromEnum(UIFont.Large):getLineHeight()
	local textY = y + (item.height - fontHgt) / 2
	self:drawText(item.text, 15, textY, 0.9, 0.9, 0.9, 0.9, UIFont.Large)
	y = y + item.height
	return y
end

function MapSpawnSelect:onGainJoypadFocus(joypadData)
    ISPanelJoypad.onGainJoypadFocus(self, joypadData)
    joypadData.focus = self.listbox
    updateJoypadFocus(joypadData)
    self.listbox:setISButtonForA(self.nextButton)
    self.listbox:setISButtonForB(self.backButton)
end

function MapSpawnSelect:onJoypadBeforeDeactivate_child(joypadData)
	self.parent:onJoypadBeforeDeactivate(joypadData)
end

function MapSpawnSelect:onJoypadBeforeDeactivate(joypadData)
	self.backButton:clearJoypadButton()
	self.nextButton:clearJoypadButton()
	-- focus is on listbox
	self.joyfocus = nil
end

function MapSpawnSelect:onJoypadDown_textEntry(button, joypadData)
	if button == Joypad.BButton then
		self:unfocus()
		self.parent.backButton:forceClick()
		return
	end
	ISTextEntryBox.onJoypadDown(self, button, joypadData)
end

function MapSpawnSelect:onJoypadDirDown_textEntry(joypadData)
	self:unfocus()
	joypadData.focus = self.parent.listbox
end

function MapSpawnSelect:onResolutionChange(oldw, oldh, neww, newh)
	self.listbox:setWidth(self.width / 2)
end

function MapSpawnSelect:create()
	local padX = 16
	local btnWid = 100
	local btnHgt = math.max(25, FONT_HGT_SMALL + 3 * 2)
	local btnPadY = 5
	local titleHgt = 80

	if not MainScreen.instance.inGame then -- don't show savefile entry in splitscreen
	
	self.textEntryLabel = ISLabel:new(20, 48, 50, getText("UI_mapselecter_savename"), 1, 1, 1, 1, UIFont.Medium, true);
	self.textEntryLabel:initialise();
	self.textEntryLabel:instantiate();
	self.textEntryLabel:setAnchorLeft(true);
	self.textEntryLabel:setAnchorRight(true);
	self.textEntryLabel:setAnchorTop(false);
	self.textEntryLabel:setAnchorBottom(false);
	self:addChild(self.textEntryLabel);
	
	local inset = 2
	self.textEntry = ISTextEntryBox:new("", self.textEntryLabel:getRight() + 17, self.textEntryLabel.y + (self.textEntryLabel.height - (FONT_HGT_MEDIUM + inset * 2)) / 2, self.width-(self.textEntryLabel:getRight() + 17) - 16, 18);
	self.textEntry.font = UIFont.Medium
	self.textEntry:initialise();
	self.textEntry:instantiate();
	self.textEntry:setAnchorLeft(true);
	self.textEntry:setAnchorRight(true);
	self.textEntry:setAnchorTop(true);
	self.textEntry:setAnchorBottom(false);
	self.textEntry.onJoypadDown = self.onJoypadDown_textEntry
	self.textEntry.onJoypadDirDown = self.onJoypadDirDown_textEntry
	self:addChild(self.textEntry);
	local sdf = SimpleDateFormat.new("dd-MM-yyyy_hh-mm-ss");
	self.textEntry:setText(sdf:format(Calendar.getInstance():getTime()));

	end -- not MainScreen.instance.inGame
	
--	self.listbox = ISScrollingListBox:new(padX, titleHgt, self.width-padX*2, self.height-btnPadY-btnHgt-24-titleHgt)
--	self.listbox:initialise()
--	self.listbox:setAnchorRight(true)
--	self.listbox:setAnchorBottom(true)
--	self.listbox.doDrawItem = MapSpawnSelect.doDrawItem
--	self.listbox:setOnMouseDoubleClick(self, MapSpawnSelect.onDblClick)
--	self:addChild(self.listbox)
	
	self.listbox = MapSpawnSelectListBox:new(16, self.startY, self.width/2, self.height-30-30-self.startY);
	self.listbox:initialise();
	self.listbox:instantiate();
	self.listbox:setAnchorLeft(true);
	self.listbox:setAnchorTop(true);
	self.listbox:setAnchorBottom(true);
	self.listbox.drawBorder = true;
	self:addChild(self.listbox);
	self.listbox.itemheight = 50;
	self.listbox.doDrawItem = MapSpawnSelect.doDrawItem
	self.listbox:setOnMouseDoubleClick(self, MapSpawnSelect.onDblClick)
	self.listbox.backgroundColor  = {r=0, g=0, b=0, a=0.5};
	
	self.richText = MapSpawnSelectInfoPanel:new(16, 10, 500,200);
	self.richText.marginRight = 20
	self.richText.autosetheight = false;
	self.richText.clip = true
	self.richText:initialise();
	self.richText.background = true;
	self.richText:setAnchorBottom(true);
	self.richText:setAnchorRight(true);
	self.richText:setVisible(false);
	self.richText.backgroundColor  = {r=0, g=0, b=0, a=0.5};
	self:addChild(self.richText);
	self.richText:addScrollBars()

	self.backButton = ISButton:new(padX, self.height - btnPadY - btnHgt, 100, btnHgt, getText("UI_btn_back"), self, MapSpawnSelect.onOptionMouseDown)
	self.backButton.internal = "BACK"
	self.backButton:initialise()
	self.backButton:instantiate()
	self.backButton:setAnchorLeft(true)
	self.backButton:setAnchorTop(false)
	self.backButton:setAnchorBottom(true)
	self.backButton.borderColor = {r=1, g=1, b=1, a=0.1}
	self:addChild(self.backButton)

	self.nextButton = ISButton:new(self.width - 116, self.height - btnPadY - btnHgt, 100, btnHgt, getText("UI_btn_next"), self, MapSpawnSelect.onOptionMouseDown)
	self.nextButton.internal = "NEXT"
	self.nextButton:initialise()
	self.nextButton:instantiate()
	self.nextButton:setAnchorLeft(false)
	self.nextButton:setAnchorRight(true)
	self.nextButton:setAnchorTop(false)
	self.nextButton:setAnchorBottom(true)
	self.nextButton:setEnable(true) -- sets the hard-coded border color
	self:addChild(self.nextButton)
end

function MapSpawnSelect:new(x, y, width, height)
	local o = ISPanelJoypad.new(self, x, y, width, height)
	o.selectedRegion = nil
	o.previousScreen = 'NewGameScreen'
	o.addY = 0;
	o.startY = MainScreen.instance.inGame and 80 or 110;
	MapSpawnSelect.instance = o
	return o
end
