-- see copyright notice in wxLdb.lua

local print = print
local wx = require( "wx" )
_G.print = print -- override wx print function with original one
local mainthread = require( "mainthread" )
local utilities = require( "grldc.utilities" )

local setmetatable = setmetatable
local assert = assert
local coroutine = coroutine
local debug = debug
local error = error
local string = string

module( "ui.promptMountPath" )

local meta = { __index = {} }

local function checkPath( user, auto )
	if auto == nil then return true end
	if string.sub( auto, 1, #user ) ~= user then
		wx.wxMessageBox( "Bad path: "..user.." not prefix of "..auto, "Error" )
		return false
	end
	local s = string.sub( auto, #user, #user )
	if s ~= "/" and s ~= "\\" then
		--print( user.." does not finish with /" )
		s = string.sub( auto, #user+1, #user+1 )
	end
	if s ~= "/" and s ~= "\\" and s ~= "" then
		wx.wxMessageBox( "Bad path: "..user.." does not finish with / and is not a parent directory of "..auto, "Error" )
		return false
	end
	return true
end

function new()
	local self = {}
	setmetatable( self, meta )
	self:initLayout_()
	return self
end

function meta.__index:destroy()
	self.dialog:Destroy()
end

function meta.__index:run( remotePath, localPath, fileName )
	if remotePath ~= nil and localPath == nil and fileName ~= nil then
		-- we can use the file open dialog to select the local file
		local fullPath = nil
		local fileDialog = wx.wxFileDialog( wx.NULL, "Find source file: "..remotePath..fileName, "", fileName, "Lua files (*.lua)|*.lua|Text files (*.txt)|*.txt|All files (*)|*", wx.wxOPEN + wx.wxFILE_MUST_EXIST )
		if fileDialog:ShowModal() == wx.wxID_OK then
			fullPath = fileDialog:GetPath()
		end
		fileDialog:Destroy()
		
		if fullPath == nil then return nil end
		
		fullPath = utilities.normalizePath( fullPath )
		
		if string.sub( fullPath, -#fileName-1 ) ~= "/"..fileName then
			wx.wxMessageBox( "Remote file and local file must have the same name", "Invalid local source file" )
			return nil
		else
			local lPath = string.sub( fullPath, 1, -#fileName-2 )
			local rPath = utilities.normalizePath( remotePath )
			--[[while true do
				print( lPath, rPath )
				local suffix
				_, _, suffix = string.find( lPath, ".*(/.+)$" )
				if suffix == nil then break end
				if string.sub( rPath, -#suffix ) ~= suffix then break end
				lPath = string.sub( lPath, 1, -#suffix-1 )
				rPath = string.sub( rPath, 1, -#suffix-1 )
			end]]
			--return rPath, lPath
			localPath = lPath
		end
	end
	assert( self.waiting == nil )
	self.waiting = coroutine.running()
	assert( self.waiting ~= nil )
	
	self.mount:SetValue( remotePath or "" )
	self.path:SetValue( localPath or "" )
	self.dialog:Show( true )
	local ok = coroutine.yield()
	assert( self.waiting == coroutine.running() )
	self.waiting = nil
	self.dialog:Show( false )
	if ok then
		local mount = self.mount:GetValue()
		local path = self.path:GetValue()
		if not checkPath( mount, remotePath ) or not checkPath( path, localPath ) then
			return self:run( remotePath, localPath )
		end
		return mount, path
	else
		return nil
	end
end

function meta.__index:initLayout_()
	self.dialog = wx.wxDialog( wx.NULL, wx.wxID_ANY, "Unknown path", wx.wxDefaultPosition, wx.wxDefaultSize )
	local panel = wx.wxPanel( self.dialog, wx.wxID_ANY )
	local vSizer = wx.wxBoxSizer( wx.wxVERTICAL )
	local sizer
	
	sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
	local label = wx.wxStaticText( panel, wx.wxID_ANY, "Please map the following remote path, or a part of it, to the corresponding local path" )
	sizer:Add( label )
	vSizer:Add( sizer )
	
	sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
	label = wx.wxStaticText( panel, wx.wxID_ANY, "remote path" )
	sizer:Add( label )
	self.mount = wx.wxTextCtrl( panel, wx.wxID_ANY )
	sizer:Add( self.mount )
	vSizer:Add( sizer )
	
	sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
	label = wx.wxStaticText( panel, wx.wxID_ANY, "local path" )
	sizer:Add( label )
	self.path = wx.wxTextCtrl( panel, wx.wxID_ANY )
	sizer:Add( self.path )
	vSizer:Add( sizer )
	
	sizer = wx.wxBoxSizer( wx.wxHORIZONTAL )
	local ok = wx.wxButton( panel, wx.wxID_ANY, "OK" )
	mainthread.execute( function()
		self.dialog:Connect( ok:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( true ) end )
	end )
	sizer:Add( ok )
	local cancel = wx.wxButton( panel, wx.wxID_ANY, "Cancel" )
	mainthread.execute( function()
		self.dialog:Connect( cancel:GetId(), wx.wxEVT_COMMAND_BUTTON_CLICKED, function() self:onEnd_( false ) end )
	end )
	sizer:Add( cancel )
	vSizer:Add( sizer )
	
	panel:SetSizer( vSizer )
	vSizer:SetSizeHints( self.dialog )
	
	mainthread.execute( function()
		self.dialog:Connect( wx.wxEVT_CLOSE_WINDOW, function() self:onEnd_( false ) end )
	end )
end

function meta.__index:onEnd_( ok )
	local status, msg = coroutine.resume( self.waiting, ok )
	assert( status, debug.traceback( self.waiting, msg ) )
end