-- Returns the relative path from 'from' to 'to'
-- If no relative path can be solved, then 'to' is returned

function Path:relative(from: string, to: string)
	local from_root, from_dir, from_basename = self:_splitPath(from)
	local to_root, to_dir, to_basename = self:_splitPath(to)

	if not self:pathsEqual(from_root, to_root) then
		return to
	end

	local from_path, to_path = from_dir .. from_basename, to_dir .. to_basename
	local common_parts = self:_commonParts(from_path, to_path)
	local from_parts = self:_splitBySeparators(from_path)
	local to_parts = self:_splitBySeparators(to_path)

	local relative_parts = {}
	if #common_parts > 0 then
		for i = #common_parts, #from_parts - 1 do
			table.insert(relative_parts, "..")
		end
	end
	for i = #common_parts + 1, #to_parts do
		table.insert(relative_parts, to_parts[i])
	end

	return self:_rawjoin(relative_parts)
end

function Path:dirname(filepath: string)
	filepath = self:normalizeSeparators(filepath)
	if filepath:sub(filepath:len()) == self.sep then
		filepath = filepath:sub(1, -2)
	end

	local root, dir = self:_splitPath(filepath)

	if #dir > 0 then
		dir = dir:sub(1, #dir - 1)
		return root .. dir
	end
	if #root > 0 then
		return root
	end
	return "."
end

function Path:basename(filepath: string, expected_ext: string)
	local _, _, base = self:_splitPath(filepath)
	if expected_ext then
		local ext_pos = base:find(expected_ext:gsub(".", ".") .. "$")
		if ext_pos then
			base = base:sub(1, ext_pos - 1)
		end
	end
	return base
end

function Path:extname(filepath: string)
	local basename = self:basename(filepath)
	if basename == ".." then
		return ""
	else
		return basename:match(".(%.[^.]*)$") or ""
	end
end

function Path:isDriveRelative()
	return false
end

function Path:isAbsolute(filepath: string)
	return filepath:sub(1, self.root:len()) == self.root
end

function Path:normalizeSeparators(filepath: string)
	return filepath
end

return {
	Path = Path,
}
