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

# 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
import os.path
import audiotools
import audiotools.text as _


def display_messages(messenger, track, messages):
    for message in messages:
        messenger.info(_.LAB_TRACKLINT_MESSAGE %
                       {"filename": audiotools.Filename(track.filename),
                        "message": message})


def audiofiles(paths, processed_filenames, messenger):
    directories = [p for p in paths if os.path.isdir(p)]
    files = [p for p in paths if os.path.isfile(p)]

    for f in audiotools.open_files(files,
                                   messenger=messenger,
                                   warn_duplicates=True,
                                   opened_files=processed_filenames):
        yield f

    for directory in directories:
        for (d, ds, fs) in os.walk(directory):
            for f in audiotools.open_files(
                    [os.path.join(d, f) for f in fs],
                    messenger=messenger,
                    warn_duplicates=True,
                    opened_files=processed_filenames):
                yield f


def update(track, messenger):
    from tempfile import mkstemp
    import shutil

    if not os.access(track.filename, os.R_OK | os.W_OK):
        raise IOError(track.filename)

    # make temporary file alongside original
    (dirname, basename) = os.path.split(track.filename)
    # may raise OSError if dir is unwriteable
    (fd, temp_path) = mkstemp(prefix="." + basename, dir=dirname)

    # perform fixes to temporary file
    try:
        fixes = track.clean(temp_path)
        shutil.copymode(track.filename, temp_path)
    except:
        os.close(fd)
        os.unlink(temp_path)
        raise

    if len(fixes) > 0:
        # overwrite original with temporary file
        os.close(fd)
        os.unlink(track.filename)
        shutil.move(temp_path, track.filename)

        # finally, display fixes performed
        display_messages(messenger, track, fixes)
    else:
        # remove temporary file
        os.close(fd)
        os.unlink(temp_path)


if (__name__ == '__main__'):
    import argparse

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

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

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

    parser.add_argument("--fix",
                        action="store_true",
                        default=False,
                        dest="fix",
                        help=_.OPT_TRACKLINT_FIX)

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

    options = parser.parse_args()

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

    processed_filenames = set()

    if options.fix:
        for track in audiofiles(options.filenames,
                                processed_filenames,
                                messenger=msg):
            try:
                update(track, msg)
            except IOError:
                msg.error(_.ERR_ENCODING_ERROR %
                          (audiotools.Filename(track.filename),))
                sys.exit(1)
            except ValueError as err:
                msg.error(unicode(err))
                sys.exit(1)
    else:  # a dry-run of the fixing procedure, with no changes made
        for track in audiofiles(options.filenames,
                                processed_filenames,
                                messenger=msg):
            display_messages(msg, track, track.clean())
