# -*- coding: utf-8 -*-

# Copyright (c) 2009, 2010, 2011, 2012 Jack Kaliko <efrim@azylum.org>
#
#  This file is part of MPD_sima
#
#  MPD_sima 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.
#
#  MPD_sima 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 MPD_sima.  If not, see <http://www.gnu.org/licenses/>.
#
#

import sys
from optparse import (OptionParser, OptionValueError, SUPPRESS_HELP)

from os import devnull
from os import (access, getcwd, W_OK, F_OK, R_OK)
from os.path import (dirname, isabs, join, normpath, exists, isdir)


USAGE = u"""USAGE:  %prog [--help] [options]"""
DESCRIPTION = u"""
MPD_sima automagicaly queue new tracks in MPD playlist.
All command line options will override their equivalent in configuration
file.
"""

# Callbacks
def is_file_rwable(option, opt_str, value, parser):
    value = normalize_path(value)
    # Check either file is write-able or not
    if not access(dirname(value), W_OK):
        raise OptionValueError('no write access to "%s"' % value)
    setattr(parser.values, option.dest, value)

def is_file_exist(option, opt_str, value, parser):
    value = normalize_path(value)
    # Check file exists and is readable
    if not access(value, F_OK):
        raise OptionValueError('no access to "%s"' % value)
    if not access(value, R_OK):
        raise OptionValueError('no read access to "%s"' % value)
    setattr(parser.values, option.dest, value)

def is_directory_rwable(option, opt_str, value, parser):
    value = normalize_path(value)
    if not exists(value):
        raise OptionValueError('"%s" does not exists' % value)
    if not isdir(value):
        raise OptionValueError('"%s" is not directory' % value)
    # Check either directory is write-able or not
    if not access(value, W_OK):
        raise OptionValueError('no write access to "%s"' % value)
    setattr(parser.values, option.dest, value)

def obsolete_option(option, opt_str, value, parser):
    raise parser.error('"%s" now obsolete' % option)#}}}


def normalize_path(path):
    """
    """
    if not isabs(path):
        return normpath(join(getcwd(), path))
    return path

def clean_dict(to_clean):
    """Remove items which values are set to None"""
    for k in to_clean.keys():
        if not to_clean.get(k):
            to_clean.pop(k)
    return to_clean


# OPTIONS LIST
# pop out 'sw' value before creating OptionParser object.
# PAY ATTENTION:
#   If an option has to override its dual in conf file, the destination
#   identifier "dest" is to be named after that option in the conf file.
#   The supersedes_config_with_cmd_line_options method in ConfMan() (config.py)
#   is looking for command line option names identical to config file option
#   name it is meant to override.
OPTS = list([
    {
        'sw':['-l', '--log'],
        'type': 'string',
        'dest':'logfile',
        'action': 'callback',
        'callback': is_file_rwable,
        'help': 'file to log message to, default is stdout/stderr'},
    {
        'sw': ['-p', '--pid'],
        'type': 'string',
        'dest': 'pidfile',
        'action': 'callback',
        'callback': is_file_rwable,
        'help': 'file to save PID to, default is not to store pid'},
    {
        'sw': ['-d', '--daemon'],
        'dest': 'daemon',
        'action': 'store_true',
        'help': 'Daemonize process.'},
    {
        'sw': ['--hostname'],
        'type': 'string',
        'dest': 'host',
        'action': 'callback',
        'callback': obsolete_option,
        'help': '[OBSOLETE] Hostname MPD in running on'},
    {
        'sw': ['-S', '--host'],
        'type': 'string',
        'dest': 'host',
        'help': 'Host MPD in running on (IP or FQDN)'},
    {
        'sw': ['-P', '--port'],
        'type': 'int',
        'dest': 'port',
        'help': 'Port MPD in listening on'},
    {
        'sw':['-c', '--config'],
        'type': 'string',
        'dest': 'conf_file',
        'action': 'callback',
        'callback': is_file_exist,
        'help': 'Configuration file to load'},
    {
        'sw':['--var_dir'],
        'type': 'string',
        'dest': 'var_dir',
        'action': 'callback',
        'callback': is_directory_rwable,
        'help': 'Directory to store var content (ie. database)'},
    {
        'sw': ['--create-db'],
        'action': 'store_true',
        'dest': 'create_db',
        'help': '''Create database and exit, use destination
                   specified in --var_dir or standard location.'''},
    {
        'sw': ['--new-version'],
        'action': 'store_true',
        'dest': 'check_new_version',
        'help': 'Check and log for new version (issue a warning)'},
    {
        'sw':['--purge_history'],
        'action': 'store_true',
        'dest': 'do_purge_history',
        'help': SUPPRESS_HELP}])


class StartOpt(object):
    """Command line management.
    """

    def __init__(self, script_info, log=None):
        self.info = dict(script_info)
        self.log = log
        self.options = dict()
        self.main()

    def declare_opts(self):
        """
        Declare options in OptionParser object.
        """
        version = "MPD_sima v%s" % self.info.get('version')
        self.parser = OptionParser(version=version,
                                   usage=USAGE,
                                   prog='mpd_sima',
                                   description=DESCRIPTION)

        # Add all options declare in OPTS
        for opt in OPTS:
            opt_names = opt.pop('sw')
            self.parser.add_option(*opt_names, **opt)

    def main(self):
        """
        Look for env. var and parse command line.
        """
        self.declare_opts()
        (options, args) = self.parser.parse_args()
        # Set log file to os.devnull in daemon mode to avoid logging to
        # std(out|err).
        if options.__dict__.get('daemon', False) and \
                not options.__dict__.get('logfile', False):
            options.__dict__['logfile'] = devnull
        self.options.update(clean_dict(options.__dict__))


if __name__ == '__main__':
    sys.exit(0)

# VIM MODLINE
# vim: ai ts=4 sw=4 sts=4 expandtab
