# audioscrobbler: ZOMG audioscrobbler functions
#   Copyright (C) 2005, 2006, 2007  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 3 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

audioscrobbler_handshake() {
  local username="$1"
  local password="$2"
  local -a http_headers
  local -a response
  local xferencoding tstamp authtoken

  tcp_open post.audioscrobbler.com 80 scrobbler || return 2
  tstamp=$(export TZ=UTC; print ${EPOCHSECONDS})
  local pwsum="$(print -n "${password}" | md5sum | awk '{print $1}')${tstamp}"
  authtoken="$(print -n "${pwsum}" | md5sum | awk '{print $1}')"
  tcp_send -s scrobbler -- "GET /?hs=true&p=1.2&c=zom&v=0.1&u=${username}&t=${tstamp}&a=${authtoken} HTTP/1.1"

  tcp_send -s scrobbler -- "Host: post.audioscrobbler.com"
  tcp_send -s scrobbler -- "Accept-Charset: utf-8"
  tcp_send -s scrobbler -- ""

  sleep 2
  tcp_read -d -s scrobbler
  tcp_close -s scrobbler

  if [[ $tcp_lines[1] != "HTTP/1."[01]" 200 OK
" ]];
  then
    return 1
  fi

  http_headers=(${tcp_lines[1,(r)
]})
  xferencoding="${${http_headers[(r)Transfer-Encoding:*]}#Transfer-Encoding: }"
  case "$xferencoding" in
    (chunked*)
    startofbody=${tcp_lines[(i)
]}
    (( startofbody++ ))
    response=(${tcp_lines[startofbody,(r)0
]})
    ;;
    (*)
    response=(${tcp_lines[(r)
,-1]})
    ;;
  esac

  local rstatus=${response[2]}
  case "$rstatus" in
    (OK)
    sessionid="${response[3]/
(#e)/}"
    npurl="$response[4]"
    submiturl="$response[5]"
    ;;
    (BANNED)
    print "Client is banned.  Try getting a newer version at http://zomg.alioth.debian.org/"
    exit 1
    ;;
    (BADAUTH)
    print "Bad authentication.  Check your credentials in ~/.zomg/conf"
    exit 1
    ;;
    (BADTIME)
    print "Time mismatch.  Check your system clock."
    exit 1
    ;;
    (FAILED *)
    print "FAILURE."

    print $rstatus
    return 1
    ;;
    (*)
    print $rstatus what the fuck
    print '[[['
    print -l ${http_headers}
    print ']]]'
    print '{{{'
    print -l ${response}
    print '}}}'
    return 1

    ;;
  esac

  as_cache_credentials "$username" "$sessionid" "$npurl" "$submiturl"
}

as_cache_credentials() {
  print "Caching credentials for $1..."
  cat >~/.zomg/ascreds.${1} <<EOF
sessionid="${2}"
npurl="${3}"
submiturl="${4}"
EOF

}

as_validate_handshake() {
  local credfile
  credfile=( ~/.zomg/ascreds.${1}(Nmm-30) )
  if [[ -f ~/.zomg/ascreds."$1" ]] && [[ -n $credfile ]];
  then
    print "Refreshing credentials for $1..."
  else
    audioscrobbler_handshake "$@" || return 1
  fi

  source ~/.zomg/ascreds."${1}"
  return 0
}

as_invalidate_handshake() {
  print "Invalidating credentials for $1."
  rm -f ~/.zomg/ascreds."$1"
}

audioscrobbler_urlencode() {
  if (( $+options[multibyte] )); then
    setopt localoptions extendedglob nomultibyte
  else
    setopt localoptions extendedglob
  fi

  input=( ${(s::)1} )
  print -- ${(j::)input/(#b)([^A-Za-z0-9_.!~*\'\(\)-])/%$(([##16]#match))}
}

audioscrobbler_constructauthtoken() {
  local password=$1
  local cr="$(print -n "${password}" | md5sum | awk '{print $1}')${challenge}"
  local challengeresponse="$(print -n "${cr}" | md5sum | awk '{print $1}')"

  print $challengeresponse
}

audioscrobbler_construct_np_query() {
  local username=$(audioscrobbler_urlencode "$1") #unused
  local sid="$2"
  local artist=$(audioscrobbler_urlencode "$3")
  local track=$(audioscrobbler_urlencode "$4")
  local album=$(audioscrobbler_urlencode "$5")
  local mbid=$(audioscrobbler_urlencode "$6")
  local length=$(audioscrobbler_urlencode "$7")
  local ttime=$(audioscrobbler_urlencode "$8") #unused
  # need tracknum

  reply=("&s=${sid}" "&a=${artist}&t=${track}&b=${album}&l=${length}&n=${tracknum}&m=${mbid}"$'\0')
}

audioscrobbler_np_submit() {
  local poststr="$1"
  local username="$2"
  local conlen=$#poststr
  local sstatus

  if (( submit == 1 ));
  then

    print "connecting to $np_submithost:$np_submitport"

    tcp_open $np_submithost $np_submitport np_mit || return 3
    tcp_send -s np_mit -- "POST /${np_submitcgi} HTTP/1.1"
    tcp_send -s np_mit -- "Host: $np_submithost"
    tcp_send -s np_mit -- "Accept-Charset: utf-8"
    tcp_send -s np_mit -- "Content-Type: application/x-www-form-urlencoded"
    tcp_send -s np_mit -- "Content-Length: $conlen"
    tcp_send -s np_mit -- ""
    tcp_send -s np_mit -- "$poststr"
    print -r "Posting to /${np_submitcgi}:"
    print -r "$poststr"

    sleep 2
    tcp_read -d -s np_mit
    tcp_close -s np_mit

    http_headers=(${tcp_lines[1,(r)
]})
    xferencoding="${${http_headers[(r)Transfer-Encoding:*]}#Transfer-Encoding: }"
    case "$xferencoding" in
      (chunked*)
      startofbody=${tcp_lines[(i)
]}
      (( startofbody+=2 ))
      response=(${tcp_lines[startofbody,(r)0
]})
      ;;
      (*)
      startofbody=${tcp_lines[(i)
]}
      (( startofbody++ ))
      response=(${tcp_lines[startofbody,-1]})
      ;;
    esac

    sstatus=${response[1]}

    print "Status: $sstatus"
    if [[ $sstatus != "OK" ]];
    then
      submit=0
      print "FAILED ($sstatus)"
      print -l "{{{" "$response" "}}}"
      return 8
    fi

  else
    return 9
  fi

}


audioscrobbler_constructquery() {
  local sid="$1"
  local artist=$(audioscrobbler_urlencode "$2")
  local track=$(audioscrobbler_urlencode "$3")
  local album=$(audioscrobbler_urlencode "$4")
  local mbid=$(audioscrobbler_urlencode "$5")
  local length=$(audioscrobbler_urlencode "$6")
  local ttime=$(audioscrobbler_urlencode "$7")
  local source="$8"
#need tracknum

  reply=("&s=${sid}" "&a[0]=${artist}&t[0]=${track}&i[0]=${ttime}&o[0]=${source}&r[0]=&l[0]=${length}&b[0]=${album}&n[0]=${tracknum}&m[0]=${mbid}"$'\0')
}

audioscrobbler_submit() {
  local poststr="$1"
  local username="$2"
  local conlen=$#poststr
  local sstatus

  if (( submit == 1 ));
  then

    print "connecting to $submithost:$submitport"

    tcp_open $submithost $submitport scrobmit || return 3
    tcp_send -s scrobmit -- "POST /${submitcgi} HTTP/1.1"
    tcp_send -s scrobmit -- "Host: $submithost"
    tcp_send -s scrobmit -- "Accept-Charset: utf-8"
    tcp_send -s scrobmit -- "Content-Type: application/x-www-form-urlencoded"
    tcp_send -s scrobmit -- "Content-Length: $conlen"
    tcp_send -s scrobmit -- ""
    tcp_send -s scrobmit -- "$poststr"
    print -r "Posting to /${submitcgi}:"
    print -r "$poststr"

    sleep 2
    tcp_read -d -s scrobmit
    tcp_close -s scrobmit

    http_headers=(${tcp_lines[1,(r)
]})
    xferencoding="${${http_headers[(r)Transfer-Encoding:*]}#Transfer-Encoding: }"
    case "$xferencoding" in
      (chunked*)
      startofbody=${tcp_lines[(i)
]}
      (( startofbody+=2 ))
      response=(${tcp_lines[startofbody,(r)0
]})
      ;;
      (*)
      startofbody=${tcp_lines[(i)
]}
      (( startofbody++ ))
      response=(${tcp_lines[startofbody,-1]})
      ;;
    esac

    sstatus=${response[1]}

    print "Status: $sstatus"
    if [[ $sstatus != "OK" ]];
    then
      submit=0
      print "FAILED ($sstatus)"
      as_invalidate_handshake "$username"
      return 8
    fi

  else
    return 9
  fi
 }
