#!/bin/zsh -i

# zomg: ZOMG
#   Copyright (C) 2005, 2006, 2007, 2008  Clint Adams

# 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 St, Fifth Floor, Boston, MA  02110-1301 USA

ZOMG_VERSION="0.3.10"

cat <<EOF;
zomg version ${ZOMG_VERSION}, Copyright (C) 2005, 2006, 2007, 2008  Clint Adams
zomg comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions.
EOF

emulate -R zsh

zmodload -i zsh/net/tcp || exit 245
zmodload -i zsh/zselect || exit 246
zmodload -i zsh/datetime || exit 247
zmodload -i zsh/parameter || exit 248

setopt extendedglob nonomatch

autoload -U tcp_open
TCP_SILENT=yes
TCP_PROMPT=
ctrlc=0

skippy()
{
  (( ctrlc++ ))
  if (( ctrlc > 1 ))
  then
    exit 0
  fi
}

#include audioscrobbler functions
source /usr/share/zomg/audioscrobbler
#
#include caching functions
source /usr/share/zomg/caching

#include urlparse functions
source /usr/share/zomg/urlparse

#include parsemedium functions
source /usr/share/zomg/parsemedium

#include shuffle functions
source /usr/share/zomg/shuffle

#include lastfmradio functions
source /usr/share/zomg/lastfmradio

if [[ ! -d ~/.zomg ]];
then
  mkdir ~/.zomg || exit 9
fi

local starttime=0 endtime=0 filetype shuffle=0 dolastfmradio=0 nonet=0 totes=0

skip=0

[[ -d /usr/lib/zomg ]] && PATH="$PATH:/usr/lib/zomg"

while getopts "nrtzh" opt; do
  case "$opt" in
    (z)
    shuffle=1
    ;;
    (r)
    dolastfmradio=1
    ;;
    (n)
    nonet=1
    ;;
    (h)
    cat <<EOF
usage: $0 [-z] [-n] [-t] musicfile1 [musicfile2] [...musicfileN]
       $0 -r [lastfm url]

  -z    shuffle tracks
  -n    do not make outgoing network connections
  -t    treat arguments as directories instead of files

  -r    last.fm radio mode
EOF
    exit 0
    ;;
    (t)
    totes=1
    ;;
    (*)
    print -- "Run $0 -h for help."
    exit 99
    ;;
  esac
done

(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))

LASTFM_USER=""
LASTFM_PASSWORD=""

if [[ ! -f ~/.zomg/conf ]];
then
  vared -p "last.fm username> " LASTFM_USER
  vared -p "last.fm password> " LASTFM_PASSWORD
  printf 'LASTFM_USER="%s"\nLASTFM_PASSWORD="%s"\n' \
  "${LASTFM_USER}" "${LASTFM_PASSWORD}" >~/.zomg/conf
fi

[[ -r ~/.zomg/conf ]] || exit 12

source ~/.zomg/conf

if (( nonet == 0 )); then

  if [[ -f ~/.zomg/cache ]];
  then
    if as_validate_handshake $LASTFM_USER $LASTFM_PASSWORD
    then
      parse_submiturl
      parse_np_submiturl
      print Flushing cache...
      audioscrobbler_flushcache $LASTFM_USER $sessionid &&
      { submit=1; mv ~/.zomg/cache ~/.zomg/cache.old } ||
	{ submit=0; as_invalidate_handshake $LASTFM_USER }
      else
	print HANDSHAKE FAILED
	submit=0
	as_invalidate_handshake $LASTFM_USER
      fi
    else
      submit=1
      as_validate_handshake $LASTFM_USER $LASTFM_PASSWORD && parse_submiturl && parse_np_submiturl || submit=0
    fi

  else
    print "Not handshaking."
    submit=0
  fi

  if (( dolastfmradio == 1 )); then
    print Connecting to Last.fm radio
    lastfm_radio "$@"
    exit 0
  else

    trap 'skippy' INT

    [[ $# -gt 0 ]] || { print "No arguments; exiting."; exit 0 }

    if (( totes == 1 )); then
      for i in "$@"
      do
       [[ -d "$i" ]] && playlist+=( $i/**/*.(ogg|mp3|flac) )
      done
    else
      playlist=("$@")
    fi

    if (( shuffle == 1 )); then
      print Shuffling $#playlist files...
      zomg_shuffle $playlist
      set -- "$reply[@]"
    else
      set -- "$playlist[@]"
    fi

    for i in "$@"
    do
      if [[ ! -r "$i" ]]; then
	  print "Cannot read file: $i; skipping"
	  continue
      fi
      case "$i" in
	(*.ogg)
	# assume vorbis
	[[ -x =zomghelper ]] && parse_zomghelper $i || parse_ogginfo $i
	trackreply=("$reply[@]")
	audioscrobbler_construct_np_query $LASTFM_USER $sessionid "$reply[1]" \
	"$reply[2]" \
	"$reply[3]" \
	"$reply[4]" \
	"$reply[5]" \
	"$EPOCHSECONDS" && audioscrobbler_np_submit ${(j::)reply} "$LASTFM_USER"
	starttime=$EPOCHSECONDS
	ogg123 --audio-buffer 2048 -v $i
	endtime=$EPOCHSECONDS
	;;
	(*.mp3)
	[[ -x =mutagen-inspect ]] && parse_mutagen $i || parse_eyeD3 $i
	trackreply=("$reply[@]")
	audioscrobbler_construct_np_query $LASTFM_USER $sessionid "$reply[1]" \
	"$reply[2]" \
	"$reply[3]" \
	"$reply[4]" \
	"$reply[5]" \
	"$EPOCHSECONDS" && audioscrobbler_np_submit ${(j::)reply} "$LASTFM_USER"
	starttime=$EPOCHSECONDS
	mpg123 -C -v $i
	endtime=$EPOCHSECONDS
	;;
	(*.flac)
	parse_mutagenflac $i
	trackreply=("$reply[@]")
	audioscrobbler_construct_np_query $LASTFM_USER $sessionid "$reply[1]" \
	"$reply[2]" \
	"$reply[3]" \
	"$reply[4]" \
	"$reply[5]" \
	"$EPOCHSECONDS" && audioscrobbler_np_submit ${(j::)reply} "$LASTFM_USER"
	starttime=$EPOCHSECONDS
	ogg123 --audio-buffer 2048 -v $i
	endtime=$EPOCHSECONDS
	;;
	(*)
	print "Unknown file extension: $i" >&2
	continue
	;;
      esac

      (( ctrlc >= 1 )) && (( ctrlc = 0 ))

      print Played for $(( endtime - starttime )) secs out of $trackreply[5] secs.
      (( endtime - starttime <= ($trackreply[5] / 2.0 ) )) &&
      (( endtime - starttime < 240 )) && skip=1

      (( $trackreply[5] < 30 )) && skip=1
      [[ -n "$trackreply[1]" && -n "$trackreply[2]" ]] || skip=1

      if [[ $skip -eq 1 ]];
      then
	print "SKIPPING"
	skip=0
      else
	audioscrobbler_constructquery "$sessionid" "$trackreply[1]" \
	"$trackreply[2]" \
	"$trackreply[3]" \
	"$trackreply[4]" \
	"$trackreply[5]" \
	"$starttime" P || exit 2
	audioscrobbler_submit ${(j::)reply} "$LASTFM_USER" || { submit=0; audioscrobbler_cache $reply[2] }
      fi
    done
  fi
