
# Copyright 2009-2013 Jaap Karssenberg <jaap.karssenberg@gmail.com>

import logging

logger = logging.getLogger('zim.config')

from zim.newfs import FileNotFoundError, LocalFolder

from .basedirs import *
from .dicts import *
from .manager import *


'''This module defines all functions and objects related to the
application config.

The sub module L{zim.config.manager} contains that L{ConfigManager}
object, which is the main object to access configuration files. In
L{zim.config.dicts} a number of classes are defined that represent
configuration files as dictionaries. And classes to define the config
options that are used and how to validate those.

The file system paths where to search for config files are defined
in L{zim.config.basedirs}.
'''


# FIXME - when XDG variables in basedirs.py change, they don't change
# in this module ...
# should they move to their own module ?

# TODO: Define a ResourceManager for loading resources (icons,
# images, templates, ..)
# Singleton class
# Avoid using basedirs directly elsewhere in the code

# TODO: resources like icons etc can be managed by a Singleton ResourceManager



def data_dirs(path=None, include_non_existing=False):
	'''Generator listing paths that contain zim data files in the order
	that they should be searched. These will be the equivalent of
	e.g. "~/.local/share/zim", "/usr/share/zim", etc.
	@param path: a file path relative to to the data dir, including this
	will list sub-folders with this relative path.
	@param include_non_existing: if C{False} only existing folders are returned
	@returns: yields L{LocalFolder} objects for the data dirs
	'''
	zimpath = ['zim']
	if path:
		if isinstance(path, str):
			path = [path]
		assert not path[0] == 'zim'
		zimpath.extend(path)

	folder = XDG_DATA_HOME.folder(zimpath)
	if include_non_existing or folder.exists():
		yield folder

	if ZIM_DATA_DIR:
		folder = ZIM_DATA_DIR.folder(path) if path else ZIM_DATA_DIR
		if include_non_existing or folder.exists():
			yield folder

	for dir in XDG_DATA_DIRS:
		folder = dir.folder(zimpath)
		if include_non_existing or folder.exists():
			yield folder


def data_dir(path):
	'''Get an data dir sub-folder.  Will look up C{path} relative
	to all data dirs and return the first one that exists. Use this
	function to find any folders from the "data/" folder in the source
	package.
	@param path:  a file path relative to to the data dir
	@returns: a L{Dir} object or C{None}
	'''
	for dir in data_dirs(path):
		if dir.exists():
			return dir
	else:
		return None


def data_file(path):
	'''Get a data file. Will look up C{path} relative to all data dirs
	and return the first one that exists. Use this function to find
	any files from the "data/" folder in the source package.
	@param path:  a file path relative to to the data dir (e.g. "zim.png")
	@returns: a L{File} object or C{None}
	'''
	for dir in data_dirs():
		file = dir.file(path)
		if file.exists():
			return file
	else:
		return None


def user_dirs():
	'''Get the XDG user dirs.
	@returns: a dict with directories for the XDG user dirs. These are
	typically defined in "~/.config/user-dirs.dirs". Common user dirs
	are: "XDG_DESKTOP_DIR", "XDG_DOWNLOAD_DIR", etc. If no definition
	is found an empty dict will be returned.
	'''
	dirs = {}
	file = XDG_CONFIG_HOME.file('user-dirs.dirs')
	try:
		for line in file.readlines():
			line = line.strip()
			if line.isspace() or line.startswith('#'):
				continue
			else:
				try:
					assert '=' in line
					key, value = line.split('=', 1)
					value = os.path.expandvars(value.strip('"'))
					dirs[key] = LocalFolder(value)
				except:
					logger.exception('Exception while parsing %s', file)
	except FileNotFoundError:
		pass
	return dirs
