#!/bin/sh

browser_cmd="brave-browser"
browser_new_cmd="brave-browser --new-window"

launch() {
	app=$(printf "Notes
	Files
	Edit
	Editor
	Open
	Pick
	Choose
	Terminal
	Multiplexer
	LBRY
	Chat
	Music
	Browser
	Hidden browser
	Email
	Page
	Go page
	Package info
	Images
	Play clipboard
	Play downloads
	Processes" | tr -d '\t' |
		dmenu -i -p "Launcher")

	case $app in 
		Notes) st -t "Notes" -e vim "+cd ~/notes/text" "+CtrlP";;
		Files) st -t "Files" -e sh -lc nnn;;
		Edit) editor;;
		Editor) st -t "Editor" -e vim "+CtrlPMRUFiles";;
		Open) opener;; 
		Pick) pick;;
		Choose) choose;;
		Terminal) st -t "Terminal";;
		Page) pages pager "$(printf "1\n2\n3\n" | dmenu -p 'page')";;
		Multiplexer) st -t "Multiplexer" -e tmux attach-session -t 0 || st -t "Multiplexer" -e tmux new-session -s 0;;
		LBRY) lbry;;
		'Go page') num=$(go_page); pages pager $num;;
		Chat) element-desktop;;
		Music) st -t "Music" -e ncmpcpp;;
		Browser) $browser_cmd;;
		'Hidden browser') $browser_cmd --incognito;;
		Email) $browser_cmd mail.protonmail.com/login;;
		Images) view_images;;
	'Play clipboard') mpv "$(xclip -o -selection clipboard)";;
	'Play downloads') mpv "$HOME/downloads/tmp/$(ls ~/downloads/tmp/ | dmenu -i -l 10 -p 'play')";;
		Processes) st -t "Processes" -e htop;;
	esac
}

action() {
	action=$(printf "Toggle Music
	Pause Music
	Play Music
	Single on
	Command
	Command to clipboard
	Select VPN
	Disable VPN
	Enable VPN
	VPN Status
	Rebind Keys
	Show calender
	Disable Bar
	Password
	Username
	Alternate password
	Download
	Download music
	Update cache
	Enable Bar" | tr -d '\t' |
		dmenu -i -p "Actions")

	case $action in
		'Play Music') mpc play ;;
		'Pause Music') mpc pause ;;
		'Toggle Music') mpc toggle;;
		'Single on') mpc toggle;;
		'Rebind Keys') setup-xbindkeys;;
		'Disable Bar') tmux set -g status off;;
		'Enable Bar') tmux set -g status on;;
		'Command') cmd;;
		'Command to clipboard') cmd_clip;;
		'Username') username;;
		'Password') password;;
		'Alternate password') other_password;;
		'Show calender') notify-send 'Calender' "\n\n$(cal)";;
		'Update cache') { mru update; mru updatedirs; };;
		#This should check for an error code and confirm that download has started
		'Download') download;;
		'Download music') download_music;;
	esac
}

login() {
	choice=$(printf "Auto
	Username
	Password
	Alternate
	Show
	Edit" | tr -d '\t' | dmenu -i -p "login")

	case $choice in
		Username) username;;
		Password) password;;
		Alternate) other_password;;
		Show) show_password;;
	esac
}

do_search() {
	type=$(printf "Manual
		DDG
		Definition
		Godocs
		Mojeek
		Package
		Github" | tr -d '\t' | dmenu -i -p "Search")
	
	case "$type" in
		Manual) p=$(man -k '' | dmenu -l 20 -p 'Manual' | cut -d' ' -f1); if [ -z $p ]; then exit; fi; st -t "Manual - $p" -e man "$p";;
		Github) github;;
		Godocs) godoc;;
		DDG) ddg;;
		Package) package;;
		Definition) word=$(printf '' | dmenu -p 'word'); if [ -z "$word" ]; then exit; fi; st -e sh -lc "dict \"$word\" | less";;
		esac
}

download() {
youtube-dl --add-metadata --no-progress -o "$HOME/downloads/%(title)s.%(ext)s" "$(xclip -selection clipboard -o)"
notify-send -u low -t 3000 "Download complete"
}
download_music() {
	youtube-dl -x --add-metadata --no-progress --audio-format mp3 -o \
		"$HOME/music/%(track)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
	if [ ! $? ]; then
		youtube-dl -x --no-progress --audio-format mp3 -o \
			"$HOME/music/%(title)s - %(artist)s.%(ext)s" "$(xclip -selection clipboard -o)"
	fi
	notify-send -u low -t 3000 "Download complete"

}

view_images() {
	d=$(mru listdirs | dmenu -l 20 -i -p 'where?')
	if [ -z "$d" ]; then exit; fi
	sxiv -r "$d"
}

package() {
	type=$(printf "search\ninfo" | dmenu -p 'package')
	if [ -z "$type" ]; then
		exit
	elif [ "$type" = "info" ]; then
		s=$(dmenu_path | dmenu -i -p 'package info')
		st -e sh -lc "apt-cache show $s"
	else
		s=$(dmenu -i -p 'package search')
		st -e sh -lc "apt search \"$s\""
	fi
}

editor() {
	#handle spacing in filenames bug
	file=$(mru list | dmenu -i -l 10 -p 'edit file')
	if [ -z "$file" ]; then exit; fi
	first=$(printf "$file" | head -n1 -)
	d=$(dirname "$first")
	files=$(printf "$file" | tr '\n' ' ')
	printf "files: $files"
	st -t 'Editor' -e vim "+cd $d" $files
}

opener() {
	mru list | dmenu -i -l 20 -p 'open' | while read f; do xdg-open "$f"; done
}

screenshot() {
	method=$(printf "clipboard
file
both" |
	dmenu -i -p "Screenshot")

	if [ $method = "file" ]; then
		scrot --note "-f 'LiterationSans Nerd Font Book/11' -x 10 -y 20 -c 255,0,0,255 -t 'Hi'"\
			-s ~/Pictures/screenshots/screenshot-%Y-%m-%d_$wx$h.png 
	fi

	if [ $method = "clipboard" ]; then
		scrot --note "-f 'LiterationSans Nerd Font Book/11' -x 10 -y 20 -c 255,0,0,255 -t 'Hi'"\
			-s ~/Pictures/screenshots/screenshot-%Y-%m-%d_$wx$h.png\
			-e "xclip $f; rm $f"
	fi

	if [ $method = "both" ]; then
		scrot --note "-f 'LiterationSans Nerd Font Book/11' -x 10 -y 20 -c 255,0,0,255 -t 'Hi'"\
			-s ~/Pictures/screenshots/screenshot-%Y-%m-%d_$wx$h.png\
			-e "xclip $f;"
	fi
}

search_type() {
	search_string="$(printf "New window\nBookmarks\nHistory" | dmenu -p "$1")"
	search_mode='tab'

	case "$search_string" in
		'New window') search_mode='window'; search_string=$(printf '' | dmenu -p "new $1");;
		'Bookmarks');;
		'History') ;;
		# *) printf "Invalid argument";;
	esac
	printf "$search_string|$search_mode"
}

brave_search() {
	search_prefix="$1"
	search_info="$(search_type "$2")"
	search_string=$(printf "$search_info" | cut -d'|' -f1)
	search_mode=$(printf "$search_info" | cut -d'|' -f2)
	if [ -z "$search_string" ]; then exit; fi
	new_string=$(rawurlencode "$search_string")
	search="$search_prefix$new_string"
	case "$search_mode" in 
		tab) $browser_cmd "$search";;
		window) $browser_new_cmd "$search";;
	esac
}

rawurlencode() {
	#Takes the first argument and encodes it
	search_string="$1"
	string_length=$(expr length "$search_string")
	char=''; new_string=''; 

	i=1
	while [ $i -le $string_length ]
	do
		char=$(expr substr "$search_string" $i 1)
		# new_string="$new_string$(rawurlencode "$char")"
		case "$char" in
			[-_.~a-zA-Z0-9] ) new_string="$new_string$char";;
				* ) new_string="$new_string%$(printf '%%%02x' "'$char")";;
		esac
		i=$(expr $i + 1)
	done
	printf "$new_string"
}

ddg() {
	brave_search "https://duckduckgo.com/?q=" "ddg"
}

github() {
	brave_search "https://github.com/search?q=" "github"
}

godoc() {
	brave_search "https://golang.org/pkg/" "godoc"
}

manual() {
	search=$(printf '' | dmenu -p 'manual')
	result=$(man "$search")
	printf "$result" | enscript -p - | ps2pdf - | zathura -
}

goinfo() {
	#Maybe this can also show recent searches
	search=$(printf "Window\nNotify" | dmenu -p 'goinfo')
	case $search in
		Window) search=$(printf '' | dmenu -p 'goinfo'); result=$(go doc "$search"); infowindow "$result"; exit;;
		Notify) search=$(printf '' | dmenu -p 'goinfo'); result=$(go doc "$search"); notify-send -u low -t 0 "Go documentation" "$result"; exit;;
	esac
	result=$(go doc "$search"); notify-send -u low -t 0 "Go documentation" "$result";
}

go_page() {
	name=$(printf "1\n2\n3\n4" | dmenu -p "page name")
	go doc "$(printf "" | dmenu -p 'go doc search')" > /tmp/pages-$name
	printf "$name"
}

infowindow() {
	printf "$1" | enscript -p - | ps2pdf - | zathura -
}

cmd() {
	c="$(printf '' | dmenu -i -p 'cmd')"

	output=$( $c )
	notify-send -u low 'command output' "$output"
}

cmd_clip() {
	value=$(cmd)
	show_value="$(expr substr "$value" 1 200)\n..."
	notify-send -u low -t 2000 "Items cliped" "$show_value"
	printf "%s" "$value" | xclip -selection clipboard
}

sel_account() {
	account=$(
	find ~/.password-store/[!\.]* -type f |
		sed -e "s:$HOME/.password-store/::" -e "s:\.gpg::" |
		dmenu -p 'account'
	)
	if [ -z "$account" ]; then exit; fi
	printf "$account"
}

username() {
	account=$(sel_account)
	if [ -z "$account" ]; then exit; fi
	name=$(pass show "$account" | sed -n -e "s/^username: //p" |
		dmenu -p 'which username' | xclip -f -selection clipboard)
	if [ -z "$name" ]; then exit; fi
	notify-send -u low -t 2000 "username copied" "$account: $name"
}

password() {
	rm prompt-login-*
	touch /tmp/prompt-login-$$
	account=$(find ~/.password-store/[!\.]* -type f |
		sed -e "s:$HOME/.password-store/::" -e "s:\.gpg::" |
		dmenu -p 'which service')
	pass -c $account
	notify-send -u low -t 1000 'password copied' "Copied $account"

}

# Giving multiple accounts for the same service the same username may cause problems.
# It assumes that the password is always the first line of the account's section, 
# and the username is always the second
other_password() {
	account=$(sel_account)
	name=$(pass show "$account" | sed -n -e "s/^username: //p" |
		dmenu -i -p 'which user password')
	if [ -z "$name" ]; then exit; fi
	copy=$(pass show $account | grep -B 1 "^username: $name" | head -n1 | tr -d '\n')
	printf "$copy" | xclip -selection clipboard
	notify-send -u low -t 2000 "password copied" "$account: $name"
	sleep 30s
	new_copy=$(xclip -o -selection clipboard)
	if [ "$copy" = $newcopy ]; then
		printf '' | xclip -selection clipboard
	fi
}

show_password() {
	account=$(sel_account)
	info=$(pass show "$account") 
	st -e sh -lc "printf '$info' | less"
}

edit_password() {
	account=$(sel_account)
		if [ -z "$account" ]; then exit; fi
		error=$(st -e pass edit "$account" 2>&1)
		if [ -n "$error" ]; then notify-send -u low -t 3000 "password edit error" "$error"; fi
	}

# Execute a command with the specified file or directory as it's argument
choose() {
	d=$(mru listdirs | dmenu -i -l 20 -p 'from')
	if [ -z "$d" ]; then exit; fi
	f=$(
	(printf "$d\n"; find "$d" -type f -not \( -path '*/.*/*' -o -path '*node_modules/*' -o -ipath '*backups/my-plugins*' -o -ipath '*/.uuid' -ipath '*.swp*' \)) |
		dmenu -i -l 20 -p 'choose file'
	)
	if [ -z "$f" ]; then exit; fi

	c=$(dmenu_path | dmenu -i -p 'operation')
	if [ -z $c ]; then exit; fi
	$c "$f"
}

vpn() {
	ls
}

# It finds all the current files in a known directory without needing to update the mru list of files
# If the directory is chosen instead of the file within it, it opens the directory with nnn
pick() {
	d=$(mru listdirs | dmenu -i -l 20 -p 'from')
	if [ -z "$d" ]; then exit; fi
	f=$(
	(printf "$d\n"; find "$d" -type f -not \( -path '*/.*/*' -o -path '*node_modules/*' -o -ipath '*backups/my-plugins*' -o -ipath '*/.uuid' -ipath '*.swp*' \)) |
		dmenu -i -l 20 -p 'pick file'
	)
	if [ -z "$f" ]; then exit; fi
	if [ "$d" = "$f" ]; then st -t 'Files' -e sh -lc "nnn '$f'"; exit; fi
	xdg-open "$f"
}

case $1 in
	launch ) launch;;
	action) action;;
	pick) pick;;
	cmd) cmd;;
	cmd_clip) cmd_clip;;
	login) login;;
	search) do_search;;
	open) opener;;
	choose) choose;;
	vpn) vpn;;
	download) download;;
	download_music) download_music;;
	*) printf "Invalid argument";;
esac