#!/opt/anaconda1anaconda2anaconda3/bin/python

# 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, see <http://www.gnu.org/licenses/>.

"""Usage: ab.py [OPTIONS] [SEARCH]

Manage your address book.

Options:
  --help                print this message and exit
  --version             print the version of the program and exit
  -a NAME EMAIL, --add=NAME EMAIL
                        add a contact to your address book
  -c, --clear           clear your address book
  -e NAME EMAIL, --edit=NAME EMAIL
                        edit a contact in your address book
  -r NAME, --remove=NAME
                        remove a contact from your address book

"""

from optparse import OptionParser
import cPickle
import os
import sys

from valentine.delvian import ab

__author__ = ab.__author__
__version__ = ab.__version__


class CLI:

    """The CLI.

    ATTRIBUTES

    ab                  The address book.
    parser              The command-line parser.

    METHODS

    __init__            Create a new CLI.
    add                 Add a contact to the address book.
    clear               Clear the address book.
    edit                Edit a contact in the address book.
    properties          Print the properties of the address book.
    remove              Remove a contact from the address book.
    run                 Run the CLI.
    version             Print the version of the program and exit.

    """

    def __init__(self):
        """Create a new CLI."""
        if os.path.exists(ab.path):
            try:
                self.ab = cPickle.load(open(ab.path, 'rb'))
            except IOError, err:
                print >> sys.stderr, err
                sys.exit('An input/output error occurred while loading your address book.')
        else:
            self.ab = ab.AddressBook()
        self.parser = OptionParser(usage='%prog [OPTIONS] [SEARCH]',
                                   description='Manage your address book.',
                                   add_help_option=False)
        self.parser.add_option('--help', action='help',
                               help='print this message and exit')
        self.parser.add_option('--version', action='callback',
                               callback=self.version,
                               help='print the version of the program and exit')
        self.parser.add_option('-a', '--add', action='callback',
                               callback=self.add, type='string', nargs=2,
                               help='add a contact to your address book',
                               metavar='NAME EMAIL')
        self.parser.add_option('-c', '--clear', action='callback',
                               callback=self.clear,
                               help='clear your address book')
        self.parser.add_option('-e', '--edit', action='callback',
                               callback=self.edit, type='string', nargs=2,
                               help='edit a contact in your address book',
                               metavar='NAME EMAIL')
        self.parser.add_option('-r', '--remove', action='callback',
                               callback=self.remove, type='string',
                               help='remove a contact from your address book',
                               metavar='NAME')

    def add(self, option, opt_str, (name, email), parser):
        """Add a contact to the address book.

        ARGUMENTS

        option          The option that was triggered.
        opt_str         The option string.
        name            The name of the contact.
        email           The email address of the contact.
        parser          The command-line parser.

        """
        try:
            self.ab.add(ab.Contact(name, email))
            cPickle.dump(self.ab, open(ab.path, 'wb'), cPickle.HIGHEST_PROTOCOL)
        except ab.ContactExistsError, err:
            print >> sys.stderr, err
        except IOError, err:
            print >> sys.stderr, err
            print >> sys.stderr, 'An input/output error occurred while saving your address book.'
        else:
            print 'Added %s to your address book.' % name

    def clear(self, option, opt_str, args, parser):
        """Clear the address book.

        ARGUMENTS

        option          The option that was triggered.
        opt_str         The option string.
        args            The arguments to the option.
        parser          The command-line parser.

        """
        if raw_input('Are you sure you want to clear your address book? (y/n) ') == 'y':
            self.ab.clear()
            try:
                cPickle.dump(self.ab, open(ab.path, 'wb'), cPickle.HIGHEST_PROTOCOL)
            except IOError, err:
                print >> sys.stderr, err
                print >> sys.stderr, 'An input/output error occurred while saving your address book.'
            else:
                print 'Cleared your address book.'
        else:
            print 'Cancelled clearing your address book.'

    def edit(self, option, opt_str, (name, email), parser):
        """Edit a contact in the address book.

        ARGUMENTS

        option          The option that was triggered.
        opt_str         The option string.
        name            The name of the contact.
        email           The email address of the contact.
        parser          The command-line parser.

        """
        try:
            self.ab.edit(ab.Contact(name, email))
            cPickle.dump(self.ab, open(ab.path, 'wb'), cPickle.HIGHEST_PROTOCOL)
        except ab.ContactDoesNotExistError, err:
            print >> sys.stderr, err
        except IOError, err:
            print >> sys.stderr, err
            print >> sys.stderr, 'An input/output error occurred while saving your address book.'
        else:
            print 'Edited %s in your address book.' % name

    def remove(self, option, opt_str, name, parser):
        """Remove a contact from the address book.

        ARGUMENTS

        option          The option that was triggered.
        opt_str         The option string.
        name            The name of the contact.
        parser          The command-line parser.

        """
        if name in self.ab:
            if raw_input('Are you sure you want to remove %s from your address book? (y/n) ' % name) == 'y':
                self.ab.remove(name)
                try:
                    cPickle.dump(self.ab, open(ab.path, 'wb'), cPickle.HIGHEST_PROTOCOL)
                except IOError, err:
                    print >> sys.stderr, err
                    print >> sys.stderr, 'An input/output error occurred while saving your address book.'
                else:
                    print 'Removed %s from your address book.' % name
            else:
                print 'Cancelled removing %s from your address book.' % name
        else:
            print >> sys.stderr, ab.ContactDoesNotExistError(name)

    def run(self, argv):
        """Run the CLI.

        ARGUMENTS

        argv            The command-line arguments.

        """
        options, args = self.parser.parse_args(argv)
        if args:
            names = self.ab.search(args)
            if names:
                for name in sorted(names):
                    print self.ab[name]
            else:
                print 'Your address book does not contain %s.' % args
        if not argv:
            if self.ab:
                for name in sorted(self.ab):
                    print self.ab[name]
            else:
                print 'Your address book is empty.'

    def version(self, option, opt_str, args, parser):
        """Print the version of the program and exit.

        ARGUMENTS

        option          The option that was triggered.
        opt_str         The option string.
        args            The arguments to the option.
        parser          The command-line parser.

        """
        print __version__
        sys.exit(0)


# Run the CLI.
if __name__ == '__main__':
    CLI().run(sys.argv[1:])

# (c) 2010 Delvian Valentine <djdvalentine@gmail.com>
