#!/usr/bin/python

#Audio Tools, a module and set of tools for manipulating audio data
#Copyright (C) 2007-2012  Brian Langenberger

#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 2 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA


import sys
import os.path
import audiotools
import audiotools.ui
import audiotools.text as _


IMAGE_TYPE_ORDER = [0, 2, 1, 3, 4]


#tries to return a populated Image object of the appropriate type
#raises InvalidImage if something goes wrong during opening or parsing
def get_image(filename, type):
    try:
        return audiotools.Image.new(open(filename, 'rb').read(), u'', type)
    except IOError:
        raise audiotools.InvalidImage(_.ERR_OPEN_IOERROR %
                                      (audiotools.Filename(filename),))


if (__name__ == '__main__'):
    parser = audiotools.OptionParser(
        usage=_.USAGE_COVERTAG,
        version="Python Audio Tools %s" % (audiotools.VERSION))

    parser.add_option(
        '-r', '--replace',
        action='store_true',
        default=False,
        dest='replace',
        help=_.OPT_TRACKTAG_REPLACE)

    #FIXME - add -I/--interactive mode
    #which should use a proper GUI, if available,
    #so one can see added images directly

    parser.add_option(
        '-V', '--verbose',
        action='store',
        dest='verbosity',
        choices=audiotools.VERBOSITY_LEVELS,
        default=audiotools.DEFAULT_VERBOSITY,
        help=_.OPT_VERBOSE)

    img_group = audiotools.OptionGroup(parser, _.OPT_CAT_IMAGE)

    for (option, destination, helptext) in [
        ('--front-cover', 'front_cover',
         _.OPT_TRACKTAG_FRONT_COVER),
        ('--back-cover', 'back_cover',
         _.OPT_TRACKTAG_BACK_COVER),
        ('--leaflet', 'leaflet',
         _.OPT_TRACKTAG_LEAFLET),
        ('--media', 'media',
         _.OPT_TRACKTAG_MEDIA),
        ('--other-image', 'other_image',
         _.OPT_TRACKTAG_OTHER_IMAGE)]:
        img_group.add_option(
            option,
            action='append',
            type='string',
            dest=destination,
            metavar='FILENAME',
            help=helptext)

    parser.add_option_group(img_group)

    (options, args) = parser.parse_args()
    msg = audiotools.Messenger("covertag", options)

    #open our set of input files for tagging
    try:
        audiofiles = audiotools.open_files(args,
                                           messenger=msg,
                                           no_duplicates=True)
    except audiotools.DuplicateFile, err:
        msg.error(_.ERR_DUPLICATE_FILE % (err.filename,))
        sys.exit(1)

    #open images for addition
    #to avoid reading the same images multiple times
    images = {}
    try:
        if (options.front_cover is not None):
            for path in options.front_cover:
                images.setdefault(0, []).append(get_image(path, 0))

        if (options.leaflet is not None):
            for path in options.leaflet:
                images.setdefault(2, []).append(get_image(path, 2))

        if (options.back_cover is not None):
            for path in options.back_cover:
                images.setdefault(1, []).append(get_image(path, 1))

        if (options.media is not None):
            for path in options.media:
                images.setdefault(3, []).append(get_image(path, 3))

        if (options.other_image is not None):
            for path in options.other_image:
                images.setdefault(4, []).append(get_image(path, 4))
    except audiotools.InvalidImage, err:
        msg.error(unicode(err))
        sys.exit(1)

    for track in audiofiles:
        #get metadata from each audio file
        metadata = track.get_metadata()

        #if metadata is present
        if (metadata is not None):
            if (metadata.supports_images()):
                #if --replace indicated, remove old images
                if (options.replace):
                    for i in metadata.images():
                        metadata.delete_image(i)

                #add images to metadata object in order
                for t in IMAGE_TYPE_ORDER:
                    for i in images.get(t, []):
                        metadata.add_image(i)

                #call update_metadata() to update track's metadata
                try:
                    track.update_metadata(metadata)
                except IOError, err:
                    msg.error(_.ERR_ENCODING_ERROR %
                              (audiotools.Filename(track.filename),))
                    sys.exit(1)
            else:
                #metadata doesn't support images, so do nothing
                pass
        else:
            #if no metadata is present, construct new MetaData object
            metadata = audiotools.MetaData()

            #add images to metadata object in order
            for t in IMAGE_TYPE_ORDER:
                for i in images.get(t, []):
                    metadata.add_image(i)

            #call set_metadata() to update track's metadata
            try:
                track.set_metadata(metadata)
            except IOError, err:
                msg.error(_.ERR_ENCODING_ERROR %
                          (audiotools.Filename(track.filename),))
                sys.exit(1)
