#!/usr/pkg/bin/python3.7

# Audio Tools, a module and set of tools for manipulating audio data
# Copyright (C) 2007-2015  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__'):
    import argparse

    parser = argparse.ArgumentParser(description=_.DESCRIPTION_COVERTAG)

    parser.add_argument("--version",
                        action="version",
                        version="Python Audio Tools %s" % (audiotools.VERSION))

    parser.add_argument("-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_argument("-V", "--verbose",
                        dest="verbosity",
                        choices=audiotools.VERBOSITY_LEVELS,
                        default=audiotools.DEFAULT_VERBOSITY,
                        help=_.OPT_VERBOSE)

    img_group = parser.add_argument_group(_.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_argument(option,
                               action="append",
                               dest=destination,
                               metavar='FILENAME',
                               help=helptext)

    parser.add_argument("filenames",
                        metavar="FILENAME",
                        nargs="+",
                        help=_.OPT_INPUT_FILENAME)

    options = parser.parse_args()

    msg = audiotools.Messenger(options.verbosity == "quiet")

    # open our set of input files for tagging
    try:
        audiofiles = audiotools.open_files(options.filenames,
                                           messenger=msg,
                                           no_duplicates=True)
    except audiotools.DuplicateFile as 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 as err:
        msg.error(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 as 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 as err:
                msg.error(_.ERR_ENCODING_ERROR %
                          (audiotools.Filename(track.filename),))
                sys.exit(1)
