#
# Copyright (C) 2009 Martin Owens
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
"""
Provide OO interface to missing xdg parts,

Example Use:

import xdgapp

# I make this var global from my project's __init__.py
# Create_dirs also allows any none existant dirs to be created (default)
MYAPP_XDG = xdgapp.XdgApplication( 'myapp', create_dirs=True )

# === Get Application Data Directory === #

# Should return '/home/[user]/Desktop'
desktop_dir = MYAPP_XDG.get_data_path( 'desktop' )

# Should return '/home/[user]/Downloads'
desktop_dir = MYAPP_XDG.get_data_path( 'downloads' )

# === Get Application Config File === #

# should return '/home/[user]/.config/appname/config.xml'
config_filename = MYAPP_XDG.get_config_file( 'config.xml' )

# Should return the contents of above or contents or
# /etc/ config (see XDG spec).
config = MYAPP_XDG.get_config( 'config.xml' )

# === Get Application Cache === #

cache_directory = MYAPP_XDG.get_cache_dir( 'cache_section' )

# This will provide you with a useful cache filename (not created)
cache_filename = MYAPP_XDG.get_cache_file( 'cache_section', 'filename.tmp', oid=unique_object_id )

# This will download a url to your apps cache and return the local filename
cached_url = MYAPP_XDG.get_url_file( 'cache_section', 'http://www.google.com/index.html', oid=oid )

"""

import os
import urllib
import logging
from xdg.BaseDirectory import (
    load_config_paths,
    xdg_config_home,
    xdg_cache_home
)
__version__ = "1.1"

class XdgApplication(object):
    """Outputs nice directories and filenames based on XDG"""
    data_paths = None

    def __init__(self, app_name, create_dirs=True):
        self.app = app_name
        self.cache_dir = os.path.join(xdg_cache_home, app_name)
        self.config_dir = os.path.join(xdg_config_home, app_name)
        self.create_dirs = create_dirs

    def reset_data_paths(self):
        """Reset the data_paths and refresh them"""
        self.data_paths = None

    def get_data_path(self, name, default):
        """Load a directory used for storing data."""
        if not self.data_paths:
            self.data_paths = {}
            content = self.get_config('user-dirs.dirs', False)
            if content:
                for line in content.split('\n'):
                    if line[:4] == 'XDG_':
                        cname, value = line.split('=')
                        value = value.replace('"','').replace('$HOME', '~')
                        key = cname[4:-4].lower()
                        if value not in ['~', '~/', '']:
                            self.data_paths[key] = value
        return self.beat_a_path(self.data_paths.get(name.lower(), default))

    def get_config_path(self):
        """Return the config path, making sure it exists"""
        return self.beat_a_path(self.config_dir)

    def get_config_file(self, filename):
        """Return the config file"""
        return os.path.join(self.get_config_path(), filename)

    def get_config(self, name, app_config=True):
        """Get an app or global config from the xdg configs"""
        if app_config:
            conf = self.get_config_file(name)
        else:
            for conf in load_config_paths(name):
                if os.path.exists(conf):
                    break
        if os.path.exists(conf):
            fh = open(conf,'r')
            content = fh.read()
            fh.close()
            return content
        logging.warning("Configuration file: '%s' doesn't exist" % conf)
        return ''

    def get_cache_dir(self, section):
        """Return a cache directory for an object id."""
        cache_dir = os.path.join(self.cache_dir, section)
        return self.beat_a_path(cache_dir)

    def get_cache_file(self, section, filename, oid=None):
        """Return a cache filename, ready to write."""
        if oid != None:
            filename = oid + "-" + filename
        directory = self.get_cache_dir(section)
        return os.path.join(directory, filename)

    def get_url_file(self, section, url, oid=None):
        """Return a filename where a url has been downloaded."""
        filename = url.split('/')[-1]
        destination = self.get_cache_file(section, filename, oid)
        if not os.path.exists(destination):
            urllib.urlretrieve( url, destination )
        return destination

    def beat_a_path(self, path):
        """Make sure a directory exists, that it's not user or relative."""
        path = self.direct_path(path)
        if not os.path.exists(path):
            if self.create_dirs:
                dir = path
                #if file:
                #    dir = os.path.dirname(path)
                logging.debug("Making directory: '%s'" % path)
                os.makedirs(path)
            else:
                raise IOError, "Directory %s doesn't exist!" % path
        return path

    def direct_path(self, path):
        """Return the most direct, absolute path"""
        if '~' in path:
            path = os.path.expanduser(path)
        if '$' in path:
            path = os.path.expandvars(path)
        if '.' in path or path[0] != '/':
            path = os.path.abspath(path)
        return path

