#!/bin/bash

# Create and cleanup temporary paths
readonly progress_file="${alfred_workflow_cache}/progress.txt"
readonly name_file="${alfred_workflow_cache}/name.txt" # for `ufp` (in Alfred)
readonly tmp_dir="$(mktemp -d)"
readonly tmp_zip_dir="$(mktemp -d)/archive"
mkdir "${tmp_zip_dir}"
trap 'rm -rf "${progress_file}" "${name_file}" "${tmp_dir}" "${tmp_zip_dir}"' EXIT

mkdir -p "${alfred_workflow_cache}"

function notification {
  ./notificator --message "${1}" --title "${alfred_workflow_name}"
}

function ascii_basename {
  basename "${1}" | sed -e 's/[^a-zA-Z0-9._-]/-/g'
}

function is_string_in_array {
  local -r string="${1}"

  for value in "${@:2}"; do
    [[ "${string}" == "${value}" ]] && return 0
  done

  return 1
}

function transfer {
  # Consolidate files bit
  # If acting on multiple files or a software bundle, first copy them to a directory
  if [[ "${#}" -gt 1 || -d "${1}/Contents" ]]; then
    cp -r "${@}" "${tmp_zip_dir}"
    local -r given_file="${tmp_zip_dir}"
  else
    local -r given_file="${1}"
  fi

  # Make zip if acting on a directory
  if [[ -d "${given_file}" ]]; then
    local -r dir_name="$(ascii_basename "${given_file}")"
    local -r zip_file="${tmp_dir}/${dir_name}.zip"
    DITTONORSRC=1 ditto -ck "${given_file}" "${zip_file}"
    local -r file_path="${zip_file}"
  else
    local -r file_path="${given_file}"
  fi

  # Escape quotes, so we can quote curl's "--form"
  # to allow for filenames with commas and semicolons
  local -r escaped_file_path="${file_path//\"/\\\"}"

  # Uploading bit
  local -r file_name="$(ascii_basename "${file_path}")"
  echo -n "${file_name}" > "${name_file}"
  notification "Uploading “${file_name}”"

  local -r hosts=('transfer.sh' '0x0.st' 'litterbox.catbox.moe' 'bashupload.com' 'bayfiles.com' 'anonfile.com' 'megaupload.is' 'forumfiles.com')
  local -r default_host="${hosts[0]}"

  if [[ -n "${upload_file_to}" ]]; then
    if is_string_in_array "${upload_file_to}" "${hosts[@]}"; then
      local -r upload_host="${upload_file_to}"
    else
      echo "Invalid upload host: ${upload_file_to}" >&2
      exit 1
    fi
  else
    local -r upload_host="${default_host}"
  fi

  if [[ "${upload_host}" == *'transfer.sh' ]]; then
    curl --globoff --progress-bar --upload-file "${file_path}" "https://${upload_host}/" 2> "${progress_file}" | tr -d '\n' | pbcopy
  elif [[ "${upload_host}" == '0x0.st' ]]; then
    curl --globoff --progress-bar --form "file=@\"${escaped_file_path}\"" "https://${upload_host}" 2> "${progress_file}" | tr -d '\n' | pbcopy
  elif [[ "${upload_host}" == 'litterbox.catbox.moe' ]]; then
    curl --globoff --progress-bar --form 'reqtype=fileupload' --form 'time=72h' --form "fileToUpload=@\"${escaped_file_path}\"" "https://${upload_host}/resources/internals/api.php" 2> "${progress_file}" | tr -d '\n' | pbcopy
  elif [[ "${upload_host}" == *'bashupload.com' ]]; then
    curl --globoff --progress-bar --upload-file "${file_path}" "https://${upload_host}/" 2> "${progress_file}" | grep '^wget' | sed 's/^wget //' | tr -d '\n' | pbcopy
  else
    curl --globoff --progress-bar --form "file=@\"${escaped_file_path}\"" "https://api.${upload_host}/upload" 2> "${progress_file}" | ruby -r 'json' -e 'data = JSON.parse(gets); abort "There was an error uploading" if data["status"] == false; puts data["data"]["file"]["url"]["full"]' | tr -d '\n' | pbcopy
  fi

  # Play sound and show message
  afplay /System/Library/Sounds/Ping.aiff
  notification "Uploaded “${file_name}”"
}

function kill_transfer {
  # Kill process tree to stop upload and prevent notification from showing success
  local -r process="$(pgrep -f 'uploadfile upload')"
  local -r process_groud_id="$(ps -o pgid= "${process}" | tr -d ' ')"
  kill -- "-${process_groud_id}"

  # Play sound and show message
  afplay /System/Library/Sounds/Funk.aiff
  notification 'Upload canceled'
}

if [[ "${1}" == 'upload' ]]; then
  shift
  transfer "${@}"
elif [[ "${1}" == 'abort' ]]; then
  kill_transfer
else
  echo 'A wrong option was given.'
  exit 1
fi
