#!/bin/bash
#Version 7
#Set variables to make script portable.
path=`realpath $0`
installdir=`dirname $path`
ARG="$1"
URL="$2"
vquality_function (){
  #Video $quality data entry detection. It will exit the script if there is no valid pattern. DASH videos won't always work in mpv, so this is why the options are limited.
  #The $tag_count variable must equal the exact number of itags provided for each quality, starting with 1.
  #Example: "tag_count=4" means that there are 4 listed itags for a particular quality. This is so the script can later check through each itag if it is present when loading a video. If the first itag in the list is not present, then it will count up and check for the next until it either discovers one that is present or falls back to a lower quality to perform the same procedure.
  #You can expirement with the order of values if you don't like a particular default.
  #itag resoure: https://gist.github.com/AgentOak/34d47c65b1d28829bb17c24c04a0096f
  #You can list itag values from youtube-dl with "youtube-dl -F <address-of-video>
  if [[ $quality = "144p" ]];
  then
    tag_count=5
    itag_1=160
    itag_2=219
    itag_3=278
    itag_4=17
    itag_5=91
  elif [[ $quality = "144p60" ]];
  then
    tag_count=1
    itag_1=330
  elif [[ $quality = "180p" ]];
  then
    tag_count=1
    itag_1=36
  elif [[ $quality = "240p" ]];
  then
    tag_count=5
    itag_1=133
    itag_2=242
    itag_3=5
    itag_4=132
    itag_5=92
  elif [[ $quality = "240p60" ]];
  then
    tag_count=1
    itag_1=331
  elif [[ $quality = "360p" ]];
  then
    tag_count=9
    itag_1=134
    itag_2=82
    itag_3=18
    itag_4=167
    itag_5=243
    itag_6=100
    itag_7=43
    itag_8=34
    itag_9=93
  elif [[ $quality = "360p60" ]];
  then
    tag_count=1
    itag_1=332
  elif [[ $quality = "480p" ]];
  then
    tag_count=11
    itag_1=135
    itag_2=168
    itag_3=218
    itag_4=244
    itag_5=245
    itag_6=246
    itag_7=44
    itag_8=35
    itag_9=83
    itag_10=94
    itag_11=101
  elif [[ $quality = "480p60" ]];
  then
    tag_count=1
    itag_1=333
  elif [[ $quality = "720p" ]];
  then
    tag_count=7
    itag_1=136
    itag_2=22
    itag_3=247
    itag_4=45
    itag_5=84
    itag_6=102
    itag_7=95
  elif [[ $quality = "720p60" ]];
  then
    tag_count=3
    itag_1=298
    itag_2=302
    itag_3=334
  elif [[ $quality = "1080p" ]];
  then
    tag_count=7
    itag_1=137
    itag_2=37
    itag_3=169
    itag_4=248
    itag_5=46
    itag_6=85
    itag_7=96
  elif [[ $quality = "1080p60" ]];
  then
    tag_count=3
    itag_1=299
    itag_2=303
    itag_3=335
  elif [[ $quality = "1440p" ]];
  then
    tag_count=2
    itag_1=264
    itag_2=271
  elif [[ $quality = "1440p60" ]];
  then
    tag_count=2
    itag_1=308
    itag_2=336
  elif [[ $quality = "2160p" ]];
  then
    tag_count=1
    itag_1=313
  elif [[ $quality = "2160p60" ]];
  then
    tag_count=4
    itag_1=138
    itag_2=266
    itag_3=315
    itag_4=337
  elif [[ $quality = "4320p" ]];
  then
    tag_count=2
    itag_1=402
    itag_2=571
  else
    printf "ERROR: Invalid option detected in streaming quality settings!\n$quality\n"
    sleep 2s
    printf "Please insert a valid option.\n"
    sleep 2s
    read -s -n 1 -p "Press any key to continue..."
    editor +12 options
    echo ""
    exit
  fi
}
aquality_function (){
  if [[ $aquality = "low" ]];
  then
    tag_audio_count=3
    itag_audio_1=250
    itag_audio_2=249
    itag_audio_3=139
  elif [[ $aquality = "medium" ]];
  then
    tag_audio_count=2
    #itag_audio_1=251
    itag_audio_2=140
    itag_audio_3=171
  elif [[ $aquality = "high" ]];
  then
    tag_audio_count=4
    itag_audio_1=258
    itag_audio_2=172
    itag_audio_3=141
    itag_audio_4=256
  else
    printf "ERROR: Invalid option detected in audio quality settings!\n$aquality\n"
    sleep 2s
    printf "Please insert a valid option.\n"
    sleep 2s
    read -s -n 1 -p "Press any key to continue..."
    editor +20 options
    echo ""
    exit
  fi
}
vidl (){
  cd $installdir/ytloader/data
  #Set variables for script.
  vlocation=$(cat options | grep "1:" | sed 's/1: //')
  mlocation=$(cat options | grep "2:" | sed 's/2: //')
  quality=$(cat options | grep "3:" | sed 's/3: //')
  display=$(cat options | grep "4:" | sed 's/4: //')
  aquality=$(cat options | grep "5:" | sed 's/5: //')
  #Verify user defined quality settings
  vquality_function
  aquality_function
  case "$ARG" in
    #stream video from mpv
    -s|--stream)
      vidl_stream
      exit 0
      ;;
    #Read URL directly from clipboard to stream video. This is useful for key macros.
    -xs|--xstream)
      URL=$(xclip -out -selection clipboard)
      vidl_stream
      echo ""
      exit 0
      ;;
    #download video with youtube-dl
    -d|--download)
      vidl_stream
      exit 0
    ;;
    #Read URL directly from clipboard to download video. This is useful for key macros.
    -xd|--xdownload)
      URL=$(xclip -out -selection clipboard)
      vidl_stream
      exit 0
      ;;
    #extract audio with youtube-dl
    -a|--audio)
      vidl_dlmp3
      exit 0
      ;;
    #Read URL directly from clipboard to download audio. This is useful for key macros.
    -xa|--xaudio)
      URL=$(xclip -out -selection clipboard)
      vidl_dlmp3
      exit 0
      ;;
    #display video info
    -i|--info)
      echo "Sorry bro, this option doesn't work anymore!"
      exit 0
      ;;
    #open ytload options with default terminal editor
    -o|--options)
      editor options
      exit 0
      ;;
    #open URL with browser
    -x|--xdg-open)
      xdg-open $URL &>/dev/null & disown
      exit 0
      ;;
    #display command flags
    -h|--help)
      printf "ytload [OPTION]... [URL]...\n-s  | --stream          Stream video of provided URL.\n-xs | --xstream         Read URL directly from clipboard to stream video\n-d  | --download        Download video with youtube-dl\n-xd | --xdownload       Read URL directly from clipboard to download video.\n-a  | --audio           Extract audio with youtube-dl\n-xa | --xaudio          Read URL directly from clipboard to download audio\n-i  | --info            Display video info.\n-o  | --options         Open ytload options with default terminal editor\n-x  | --xdg-open        Open URL with browser\n-h  | --help\n"
      exit 0
      ;;
    #catch bad arguments
    *)
      printf "ERROR: $ARG is an unknown option!\n"
      exit 0
      ;;
  esac
  exit 0
}
vidl_stream (){
  #Check video source
  vid_source=$(echo $URL | grep -i youtu)
  if [ -z $vid_source ];
  then
    echo "Not a youtube source..."
    mpv $URL
  else
    echo "Loading video. Please wait..."
    #Store video itags into a variable.
    quality_list=$(youtube-dl -F $URL | cut -d' ' -f1 | grep -o '[0-9]*')
    #Check if defined quality is available. If the defined quality is not available, then fallback onto a lower quality from the user defined setting.
    quality_check_ct=1
    quality_check=false
    until [ $quality_check_ct -gt 1 ]  
    do
      tag_counter=1
      counter=1
      # While the $counter variable is less than or equal to $tag_count...
      while [ $counter -le $tag_count ]
      do
        # Declare the $var_pointer variable, which will contain "itag_1" as its base value due to the $tag_counter.
        var_pointer="itag_$tag_counter"
        # Declare the $itag_count variable, which will variablize the value of $var_pointer to dynamically set the $itag_1,2,3,4 etc variables (from which the values of $itag_1,2,3,4 etc are declared during the inital quality check in the vquality_function.)
        itag_count="${!var_pointer}"
        # If the $itag_count value is present in the $quality_list...
        if grep -Fq "$itag_count" <<< "$quality_list"
        then
          # Then increase the $quality_check_ct value by 1 and set $quality_check to true since the video quality is present.
          ((quality_check_ct++))
          quality_check="true"
          counter=999
          echo "QUALITY_CHECK: $quality exists."
        else
          ((tag_counter++))
        fi
        ((counter++))
      done
      if [[ "$quality_check" = "false" ]]
      then
        echo "QUALITY_CHECK: $quality for this video does not exist! Checking for fallback."
        #Falling back to an available quality
        if [[ $quality = "2160p60" ]];
        then
          quality=2160p
          vquality_function
        elif [[ $quality = "2160p" ]];
        then
          quality=1440p
          vquality_function
        elif [[ $quality = "1440p60" ]];
        then
          quality=1440p
          vquality_function
        elif [[ $quality = "1440p" ]];
        then
          quality=1080p
          vquality_function
        elif [[ $quality = "1080p60" ]];
        then
          quality=1080p
          vquality_function
        elif [[ $quality = "1080p" ]];
        then
          quality=720p
          vquality_function
        elif [[ $quality = "720p60" ]];
        then
          quality=720p
          vquality_function
        elif [[ $quality = "720p" ]];
        then
          quality=480p
          vquality_function
        elif [[ $quality = "480p60" ]];
        then
          quality=480p
          vquality_function
        elif [[ $quality = "480p" ]];
        then
          quality=360p
          vquality_function
        elif [[ $quality = "360p60" ]];
        then
          quality=360p
          vquality_function
        elif [[ $quality = "360p" ]];
        then
          quality=240p
          vquality_function
        elif [[ $quality = "240p60" ]];
        then
          quality=240p
          vquality_function
        elif [[ $quality = "240p" ]];
        then
          quality=180p
          vquality_function
        elif [[ $quality = "180" ]];
        then
          quality=144p
          vquality_function
        elif [[ $quality = "144p60" ]];
        then
          quality=144p
          vquality_function
        elif [[ $quality = "144p" ]];
        then
          printf "QUALITY_CHECK: Error, no video qualities are available!\nQUALITY_CHECK: FAIL"
          exit 1
        else
          printf "QUALITY_CHECK: Error, no video qualities are available!\nQUALITY_CHECK: FAIL"
          exit 1
        fi
      fi
    done
    # Now check if the user defined audio quality is available
    aquality_check_ct=1
    aquality_check=false
    until [ $aquality_check_ct -gt 1 ]  
    do
      atag_counter=1
      acounter=1
      while [ "$acounter" -le "$tag_audio_count" ]
      do
        # Declare the $avar_pointer variable, which will contain "itag_audio_1" as its base value due to the $atag_counter.
        avar_pointer="itag_audio_$atag_counter"
        # Declare the $aitag_count variable, which will variablize the value of $avar_pointer to dynamically set the $itag_audio_1,2,3,4 etc variables (from which the values of $itag_audio_1,2,3,4 etc are declared during the inital quality check in the vidl function.)
        aitag_count="${!avar_pointer}"
        # If the $aitag_count value is present in the $quality_list...
        if grep -Fq "$aitag_count" <<< "$quality_list"
        then
          # Then set $aquality_check to true since the audio quality is present.
          ((aquality_check_ct++))
          aquality_check=true
          acounter=999
          echo "AUDIO_QUALITY_CHECK: $aquality exists."
        elif [[ $aquality = "none" ]];
        then
          #If there is no known audio format, then let's just forget about it. Live streams won't have a seperate audio format, so this would be a good default.
          ((aquality_check_ct++))
          aquality_check=true
          acounter=999
        else
          ((atag_counter++))
        fi
        ((acounter++))
      done
      # If $aquality_check is still false, then try to fallback from the user defined setting.
      if [[ "$aquality_check" = "false" ]];
      then
        echo "AUDIO_QUALITY_CHECK: $aquality audio quality for this video does not exist! Checking for fallback."
        #Falling back to an available quality
        if [[ $aquality = "high" ]];
        then
          aquality=medium
          aquality_function
        elif [[ $aquality = "medium" ]];
        then
          aquality=low
          aquality_function
        elif [[ $aquality = "low" ]];
        then
          printf "AUDIO_QUALITY_CHECK: Warning, no audio qualities are available!\nAUDIO_QUALITY_CHECK: MISSING\n"
          aquality=none
        else
          printf "AUDIO_QUALITY_CHECK: Warning, no audio qualities are available!\nAUDIO_QUALITY_CHECK: MISSING\n"
          aquality=none
        fi
      fi
    done
    #This first check is made up in case the loop above was improperly exited. This will prevent the script from continuing to attempt to load the video in that condition.
    if [[ "$quality_check" = "true" ]];
    then
      if [[ "$aquality_check" = "true" ]];
      then
        if [[ "$aquality" = "none" ]];
        then
          case "$ARG" in
            #stream video from mpv
            -s|--stream|-xs|--xstream)
            echo "CHECK: PASS"
            echo "mpv $display --ytdl-format=$itag_count $URL"
            mpv $display --ytdl-format=$itag_count $URL
            ;;
            #download video with youtube-dl
            -d|--download|-xd|--xdownload)
            echo "CHECK: PASS"
            echo "youtube-dl -f $itag_count $URL -o $vlocation"
            youtube-dl -f $itag_count $URL -o $vlocation
            ;;
          esac
        else
          case "$ARG" in
            #stream video from mpv
            -s|--stream|-xs|--xstream)
            #echo "QUALITY_CHECK: $quality exists."
            #echo "AUDIO_QUALITY_CHECK: $aquality exists."
            echo "CHECK: PASS"
            echo "mpv $display --ytdl-format=$itag_count+$aitag_count $URL"
            mpv $display --ytdl-format=$itag_count+$aitag_count $URL
            ;;
            #download video with youtube-dl
            -d|--download|-xd|--xdownload)
            #echo "QUALITY_CHECK: $quality exists."
            #echo "AUDIO_QUALITY_CHECK: $aquality exists."
            echo "CHECK: PASS"
            echo "youtube-dl -f $itag_count+$aitag_count $URL -o $vlocation"
            youtube-dl -f $itag_count+$aitag_count $URL -o $vlocation
            ;;
          esac
        fi
      fi
    else
      #This shouldn't be needed, but it's here just in case.
      #echo "QUALITY_CHECK: Error, improper loop exit on false value."  
      #echo "QUALITY_CHECK: FAIL"
      #sleep 2s
      #read -s -n 1 -p "Press any key to exit..."
      echo "HEY"
    fi
  fi
}
vidl_dlmp3 (){
  youtube-dl --extract-audio --audio-format mp3 $URL -o $mlocation
  #Notify user
  if [ $? -eq 0 ];
  then
    notify-send "Your audio file finished downloading."
  else
    notify-send "There was an error while downloading the audio file."
  fi
}
vidl
