#!/usr/bin/python

# 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 time
import termios
import os
import audiotools
import audiotools.ui
import audiotools.player
import audiotools.text as _

if audiotools.ui.AVAILABLE:
    urwid = audiotools.ui.urwid

    class TrackplayGUI(audiotools.ui.PlayerGUI):
        def __init__(self, track_list, audio_output,
                     replay_gain=audiotools.player.RG_NO_REPLAYGAIN):
            def track_name(track):
                metadata = track.get_metadata()
                if (((metadata is not None) and
                     (metadata.track_name is not None))):
                    return metadata.track_name
                else:
                    return audiotools.Filename(
                        track.filename).basename().__unicode__()

            audiotools.ui.PlayerGUI.__init__(
                self,
                audiotools.player.Player(
                    audio_output=audio_output,
                    replay_gain=replay_gain,
                    next_track_callback=self.next_track),
                [(track_name(track), int(track.seconds_length()),
                  (track, track.get_metadata())) for track in track_list],
                sum([track.seconds_length() for track in track_list]))

        def select_track(self, radio_button, new_state, user_data,
                         auto_play=True):
            if new_state:
                (track, metadata) = user_data
                if metadata is not None:
                    self.update_metadata(
                        track_name=metadata.track_name,
                        album_name=metadata.album_name,
                        artist_name=metadata.artist_name,
                        track_number=metadata.track_number,
                        track_total=metadata.track_total,
                        album_number=metadata.album_number,
                        album_total=metadata.album_total,
                        pcm_frames=track.total_frames(),
                        channels=track.channels(),
                        sample_rate=track.sample_rate(),
                        bits_per_sample=track.bits_per_sample())

                else:
                    self.update_metadata(
                        pcm_frames=track.total_frames(),
                        channels=track.channels(),
                        sample_rate=track.sample_rate(),
                        bits_per_sample=track.bits_per_sample())

                self.player.open(track)
                if auto_play:
                    from audiotools.text import LAB_PAUSE_BUTTON

                    self.player.play()
                    self.play_pause_button.set_label(LAB_PAUSE_BUTTON)

    interactive_available = True
else:
    interactive_available = False


class TrackplayTTY(audiotools.ui.PlayerTTY):
    def __init__(self, track_list, audio_output,
                 replay_gain=audiotools.player.RG_NO_REPLAYGAIN):
        self.track_index = -1
        self.track_list = track_list
        audiotools.ui.PlayerTTY.__init__(
            self,
            audiotools.player.Player(
                audio_output=audio_output,
                replay_gain=replay_gain,
                next_track_callback=self.next_track))

    def previous_track(self):
        if self.track_index > 0:
            self.track_index -= 1
            current_track = self.track_list[self.track_index]
            self.set_metadata(
                track_number=self.track_index + 1,
                track_total=len(self.track_list),
                channels=current_track.channels(),
                sample_rate=current_track.sample_rate(),
                bits_per_sample=current_track.bits_per_sample())
            self.player.open(current_track)
            self.player.play()

    def next_track(self):
        try:
            self.track_index += 1
            current_track = self.track_list[self.track_index]
            self.set_metadata(
                track_number=self.track_index + 1,
                track_total=len(self.track_list),
                channels=current_track.channels(),
                sample_rate=current_track.sample_rate(),
                bits_per_sample=current_track.bits_per_sample())
            self.player.open(current_track)
            self.player.play()
        except IndexError:
            self.playing_finished = True


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

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

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

    parser.add_argument("-I", "--interactive",
                        action="store_true",
                        default=False,
                        dest="interactive",
                        help=_.OPT_INTERACTIVE_OPTIONS)

    parser.add_argument("-o", "--output",
                        dest="output",
                        choices=[player.NAME for player in
                                 audiotools.player.available_outputs()],
                        default=[player.NAME for player in
                                 audiotools.player.available_outputs()][0],
                        help=_.OPT_OUTPUT_PLAY)

    parser.add_argument("-T", "--track-replaygain",
                        action="store_true",
                        default=False,
                        dest="track_replaygain",
                        help=_.OPT_PLAYBACK_TRACK_GAIN)

    parser.add_argument("-A", "--album-replaygain",
                        action="store_true",
                        default=False,
                        dest="album_replaygain",
                        help=_.OPT_PLAYBACK_ALBUM_GAIN)

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

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

    options = parser.parse_args()
    msg = audiotools.Messenger()

    if options.interactive and (not interactive_available):
        msg.error(_.ERR_URWID_REQUIRED)
        msg.output(_.ERR_GET_URWID1)
        msg.output(_.ERR_GET_URWID2)
        sys.exit(1)

    audiofiles = []
    for filename in map(audiotools.Filename, options.filenames):
        try:
            audiofile = audiotools.open(str(filename))
            if audiofile.__class__.supports_to_pcm():
                audiofiles.append(audiofile)
            else:
                msg.warning(_.ERR_UNSUPPORTED_TO_PCM %
                            {"filename": filename,
                             "type": audiofile.NAME})
        except audiotools.UnsupportedFile:
            msg.warning(_.ERR_UNSUPPORTED_FILE % (filename,))
        except audiotools.InvalidFile as err:
            msg.warning(str(err))
        except IOError:
            msg.warning(_.ERR_OPEN_IOERROR % (filename,))

    if options.shuffle:
        import random

        random.shuffle(audiofiles)

    if options.track_replaygain:
        replay_gain = audiotools.player.RG_TRACK_GAIN
    elif options.album_replaygain:
        replay_gain = audiotools.player.RG_ALBUM_GAIN
    else:
        replay_gain = audiotools.player.RG_NO_REPLAYGAIN

    if options.interactive:
        trackplay = TrackplayGUI(
            track_list=audiofiles,
            audio_output=audiotools.player.open_output(options.output),
            replay_gain=replay_gain)

        if len(audiofiles) > 0:
            trackplay.select_track(None, True,
                                   (audiofiles[0],
                                    audiofiles[0].get_metadata()), False)

        loop = urwid.MainLoop(trackplay,
                              audiotools.ui.style(),
                              screen=audiotools.ui.Screen(),
                              unhandled_input=trackplay.handle_text,
                              pop_ups=True)

        loop.set_alarm_at(tm=time.time() + 1,
                          callback=audiotools.ui.timer,
                          user_data=trackplay)

        try:
            loop.run()
            msg.ansi_clearscreen()
        except (termios.error, IOError):
            msg.error(_.ERR_TERMIOS_ERROR)
            msg.info(_.ERR_TERMIOS_SUGGESTION)
            msg.info(audiotools.ui.xargs_suggestion(sys.argv))
            sys.exit(1)
    else:
        trackplay = TrackplayTTY(
            track_list=audiofiles,
            audio_output=audiotools.player.open_output(options.output),
            replay_gain=replay_gain)
        sys.exit(trackplay.run(msg, sys.stdin))
