#!/bin/sh

set -eu

# Parse options

base=true
nicetohave=true
go=false
rust=false
deno=false
rootzsh=false
desktopbase=false
desktop=false
pwn=false

while [ $# != 0 ]; do
	case "$1" in
		nobase) base=false;;
        base) base=true;;
		nonicetohave) nicetohave=false;;
		nicetohave) nicetohave=true;;
		nogo) go=false;;
		go) go=true;;
		norust) rust=false;;
		rust) rust=true;;
		nodeno) deno=false;;
		deno) deno=true;;
		norootzsh) rootzsh=false;;
		rootzsh) rootzsh=true;;
		nodesktopbase) desktopbase=false;;
		desktopbase) desktopbase=true;;
		nodesktop) desktopbase=false desktop=false;;
		desktop) desktopbase=true desktop=true;;
		nopwn) pwn=false;;
		pwn) pwn=true;;
		*) echo "Unknown flag: $1"; exit 1;;
	esac
	shift
done

# Parse platforms into a friendly format

case "$(uname -s)" in
	Darwin)
		PLATFORM=macos
		ID=macos
		VERSION_ID=$(sw_vers -productVersion)
		;;
	Linux)
		PLATFORM=linux
		. /etc/os-release
		;;
	*)
		PLATFORM=unsupported
		ID=unsupported
		VERSION_ID=unsupported
		;;
esac

if [ "$ID" = fedora ] && [ "${VARIANT_ID:-}" = coreos ]; then
	ID=coreos # Fedora CoreOS
fi

# Package installation helpers

packages=""
packages_add() {
	packages="$packages $@"
}
packages_install() {
	if [ -z "$packages" ]; then
		return
	fi
	case $ID in
		macos)
			brew install --formulae $packages
			;;
		alpine)
			sudo apk add --no-cache --update $packages
			;;
		fedora)
			sudo dnf install -y $packages
			sudo dnf clean all
			sudo rm -rf /var/cache/dnf
			;;
		debian|ubuntu)
			sudo apt-get update
			sudo DEBIAN_FRONTEND=noninteractive apt-get install -y $packages
			sudo rm -rf /var/lib/apt/lists/*
			;;
	esac
	packages=""
}

# Installation into user folder

download_bin_path="$HOME/.local/bin"
mkdir -p "$download_bin_path"
download_dust() {
	version=v0.7.5
	arch=x86_64
	case $ID in
		macos) system=apple-darwin;;
		alpine) system=unknown-linux-musl;;
		fedora|debian|ubuntu) system=unknown-linux-gnu;;
	esac
	wget \
		--output-document /tmp/dust.tar.gz \
		https://github.com/bootandy/dust/releases/download/$version/dust-$version-$arch-$system.tar.gz
	tar -x \
		--gunzip \
		--file /tmp/dust.tar.gz \
		--to-stdout \
		dust-$version-$arch-$system/dust > "$download_bin_path/dust"
	rm /tmp/dust.tar.gz
}
download_ripgrep() {
	version=13.0.0
	arch=x86_64
	case $ID in
		macos) system=apple-darwin;;
		alpine) system=unknown-linux-musl;;
		*) return 1;;
	esac
	wget \
		--output-document /tmp/ripgrep.tar.gz \
		https://github.com/BurntSushi/ripgrep/releases/download/$version/ripgrep-$version-$arch-$system.tar.gz
	tar -x \
		--gunzip \
		--file /tmp/ripgrep.tar.gz \
		--to-stdout \
		ripgrep-$version-$arch-$system/dust > "$download_bin_path/ripgrep"
	rm /tmp/ripgrep.tar.gz
}
download_kitty_terminfo() {
	version=master
	mkdir -p "$HOME/.terminfo/x"
	wget \
		--output-document "$HOME/.terminfo/x/xterm-kitty" \
		"https://github.com/kovidgoyal/kitty/raw/$version/terminfo/x/xterm-kitty"
}
download_kubectl() {
	version=$(wget --quiet --output-document - https://dl.k8s.io/release/stable.txt)
	arch=amd64
	case $PLATFORM in
		macos) system=darwin;;
		linux) system=linux;;
		*) return 1;;
	esac
	wget \
		--output-document "$download_bin_path/kubectl" \
		https://dl.k8s.io/release/$version/bin/$system/$arch/kubectl
	chmod +x "$download_bin_path/kubectl"
}
download_minio_client() {
	arch=amd64
	case $PLATFORM in
		macos) system=darwin;;
		linux) system=linux;;
		*) return 1;;
	esac
	wget \
		--output-document "$download_bin_path/mc" \
		https://minio.mirror.makerforce.io/client/mc/release/$system-$arch/mc
		#https://dl.min.io/client/mc/release/$system-$arch/mc
	chmod +x "$download_bin_path/mc"
}
download_nvim_plug() {
	version=master
	mkdir -p "$HOME/.config/nvim/autoload"
	wget \
		--output-document "$HOME/.config/nvim/autoload/plug.vim" \
		https://github.com/junegunn/vim-plug/raw/$version/plug.vim
}
download_go() {
	version=1.17.1
	arch=amd64
	case $PLATFORM in
		macos) system=darwin;;
		linux) system=linux;;
		*) return 1;;
	esac
	wget \
		--output-document /tmp/go.tar.gz \
		https://golang.org/dl/go$version.$system-$arch.tar.gz
	sudo tar -x \
		--gunzip \
		--directory /usr/local \
		--file /tmp/go.tar.gz
	restore_cd="$(pwd)"
	cd /usr/local/bin
	sudo ln -s /usr/local/go/bin/go
	sudo ln -s /usr/local/go/bin/gofmt
	cd "$restore_cd"
	rm /tmp/go.tar.gz
}
download_rust() {
	wget --output-document - https://sh.rustup.rs | sh -s -- -y
}
download_deno() {
	wget --output-document - https://deno.land/x/install/install.sh | sh -s
}
download_font_path="$HOME/.local/share/fonts"
mkdir -p "$download_font_path"
download_font_firacode() {
	version=5.2
	wget \
		--output-document /tmp/firacode.zip \
		https://github.com/tonsky/FiraCode/releases/download/$version/Fira_Code_v$version.zip
	unzip -q /tmp/firacode.zip -d /tmp/firacode
	mv /tmp/firacode/ttf/* "$download_font_path/"
	rm -r /tmp/firacode.zip /tmp/firacode
}
download_font_ibmplex() {
	version=5.2.1
	wget \
		--output-document /tmp/ibmplex.zip \
		https://github.com/IBM/plex/releases/download/v$version/TrueType.zip
	unzip -q /tmp/ibmplex.zip -d /tmp/ibmplex
	for family in Sans Serif Mono; do
		mv /tmp/ibmplex/TrueType/IBM-Plex-$family/*.ttf "$download_font_path/"
	done
	rm -r /tmp/ibmplex.zip /tmp/ibmplex
}
download_cutter_re() {
	version=2.0.3
	case $PLATFORM in
		linux) system=Linux;;
		*) return 1;;
	esac
	wget \
		--output-document "$download_bin_path/cutter" \
		https://github.com/rizinorg/cutter/releases/download/v$version/Cutter-v$version-x64.$system.AppImage
	chmod +x "$download_bin_path/cutter"
}

# Install basics

packages_add openssl wget upx
case $PLATFORM in
	linux) packages_add tar gzip;;
esac
case $PLATFORM in
	macos|alpine|fedora) packages_add xz;;
	debian|ubuntu) packages_add xz-utils;;
esac

if $base; then

	# Install shell

	packages_add zsh zsh-autosuggestions zsh-syntax-highlighting
	case $ID in
		alpine) packages_add zsh-vcs ncurses;;
		fedora) packages_add ncurses;;
		debian|ubuntu) packages_add ncurses-bin;;
	esac

	# Install editor, management and security tools

	packages_add neovim git
	case $ID in
		alpine|debain|ubuntu) packages_add xxd;;
		fedora) packages_add vim-common;;
	esac
	$nicetohave && packages_add pass gnupg
	case $ID in
		macos) packages_add pinentry-mac;;
		alpine) packages_add dropbear-ssh;;
		fedora) packages_add openssh-clients;;
		debian|ubuntu) packages_add openssh-client;;
	esac
	packages_add exa jq

	# Install C compilers

	case $ID in
		alpine) $nicetohave && packages_add alpine-sdk linux-headers;;
		fedora) $nicetohave && packages_add kernel-headers;;
		debian|ubuntu) $nicetohave && packages_add build-essential;;
	esac

	# Install Python 3

	case $ID in
		macos) packages_add python@3;;
		alpine|fedora|debian|ubuntu) packages_add python3;;
	esac
	case $ID in
		alpine|debian|ubuntu) $nicetohave && packages_add python3-dev;;
		fedora) $nicetohave && packages_add python3-devel;;
	esac
	case $ID in
		alpine) $nicetohave && packages_add py3-pip;;
		fedora|debian|ubuntu) $nicetohave && packages_add python3-pip;;
	esac
	packages_install

	# Install dust

	case $ID in
		macos|alpine) $nicetohave && packages_add dust;;
		*) $nicetohave && download_dust;;
	esac

	# Install ripgrep

	case $ID in
		macos|alpine|fedora|debian|ubuntu) $nicetohave && packages_add ripgrep;;
		*) $nicetohave && download_ripgrep;;
	esac

	# Install kitty terminfo
	case $ID in
		macos|alpine) download_kitty_terminfo;;
		fedora|debian|ubuntu) packages_add kitty-terminfo;;
	esac

	# Install Python 3 packages

	case $ID in
		macos|alpine|fedora|debian|ubuntu) $nicetohave && packages_add httpie;;
		*) $nicetohave && pip3 install --no-cache-dir --user httpie;;
	esac
	case $ID in
		macos|fedora|debian|ubuntu) $nicetohave && packages_add thefuck;;
		*) $nicetohave && pip3 install --no-cache-dir --user thefuck;;
	esac

	# Install Golang

	case $ID in
		#macos) $go && packages_add go;;
		#alpine) $go && packages_add go;;
		#fedora) $go && packages_add golang;;
		*) $go && download_go;;
	esac

	# Install Rust

	$rust && download_rust
	$rust && source "$HOME/.cargo/env" && rustup component add rls rust-analysis rust-src

	# Install deployment utilities

	$nicetohave && download_kubectl
	$nicetohave && download_minio_client

	# Install editor plugins

	# Plug install
	download_nvim_plug
	nvim +PlugInstall +qa || true

	# Install graphics tools

	case $ID in
		fedora) $nicetohave && packages_add GraphicsMagick;;
		*) $nicetohave && packages_add graphicsmagick;;
	esac

	# Final packages installation

	packages_install

	# Give root a ZSH prompt

	sudo cp "$HOME/.zshrc" /root/.zshrc

fi

if $desktopbase; then

	case $ID in
		debian)
			if ! grep --quiet 'unstable' /etc/apt/sources.list; then
				echo "WARN: debian unstable required"
				exit 1
			fi
			if ! grep --quiet 'contrib' /etc/apt/sources.list; then
				echo "WARN: contrib required"
				echo "WARN: enabling contrib"
				echo "deb http://deb.debian.org/debian unstable contrib" | sudo tee /etc/apt/sources.list
			fi
			;;
		fedora)
			if ! rpm -qa | grep --quiet 'rpmfusion-free'; then
				echo "WARN: rpmfusion free requried"
				echo "WARN: enabling rpmfusion free"
				sudo dnf install -y \
					"https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-$(rpm -E %fedora).noarch.rpm"
			fi
			;;
	esac

	# desktopbase: Fonts

	case $ID in
		alpine) packages_add \
			font-noto-emoji
			download_font_firacode
			download_font_ibmplex
			;;
		fedora) packages_add \
			ibm-plex-sans-fonts ibm-plex-serif-fonts ibm-plex-mono-fonts \
			fira-code-fonts \
			google-noto-emoji-color-fonts \
			;;
		debian|ubuntu) packages_add \
			fonts-ibm-plex \
			fonts-firacode \
			fonts-noto-color-emoji \
			;;
	esac
	case $ID in
		alpine) $nicetohave && packages_add \
			font-noto \
			font-noto-cjk \
			;;
		fedora) $nicetohave && packages_add \
			google-noto-sans-fonts google-noto-serif-fonts \
			google-noto-cjk-fonts \
			;;
		debian|ubuntu) $nicetohave && packages_add \
			fonts-noto-core \
			fonts-noto-cjk \
			;;
	esac

	# desktopbase: Desktop theme

	case $ID in
		alpine|fedora|debian|ubuntu) packages_add \
			gsettings-desktop-schemas \
			gnome-themes-extra \
			adwaita-icon-theme \
			;;
	esac
	case $ID in
		debian|ubuntu) packages_add adwaita-qt;;
		fedora) packages_add adwaita-qt5;;
	esac

	# desktopbase: Final packages installation

	packages_install

fi

if $desktopbase && $desktop; then

	# desktop: Install sway

	case $ID in
		alpine|fedora|debian|ubuntu) packages_add \
			sway swaybg swayidle swaylock \
			waybar wofi \
			\
			lxpolkit \
			grim slurp \
			playerctl \
			;;
	esac

	case $ID in
		alpine|fedora) packages_add mako;;
		debian|ubuntu) packages_add mako-notifier;;
	esac

	case $ID in
		fedora) echo "WARN: $ID has no stable wf-recorder package";;
		alpine|debian|ubuntu) packages_add wf-recorder;;
	esac

	case $ID in
		alpine|fedora) packages_add pinentry-gtk;;
		debian|ubuntu) packages_add pinentry-gtk2;;
	esac

	# desktop: Install applications

	case $ID in
		alpine) echo "WARN: $ID has no stable ddcutil and kitty packages";;
		fedora|debian|ubuntu) packages_add ddcutil kitty;;
	esac

	case $ID in
		macos) brew install --cask \
			firefox \
			iterm2 docker paw \
			coolterm \
			;;
		*) packages_add \
			firefox \
			;;
	esac

	# desktop: Final packages installation

	packages_install

fi

if $pwn; then

	case $ID in
		debian)
			if ! grep --quiet 'unstable' /etc/apt/sources.list; then
				echo "WARN: debian unstable required"
				exit 1
			fi
			;;
	esac

	# pwn: Build dependencies for most

	case $ID in
		alpine|fedora|debian|ubuntu) packages_add cmake make gcc g++;;
	esac

	# pwn: Build dependencies for stegseek

	case $ID in
		alpine) packages_add libmhash-dev libmcrypt-dev libjpeg-turbo-dev zlib-dev;;
		fedora) packages_add mhash-devel libmcrypt-devel libjpeg-turbo-devel zlib-devel;;
		debian|ubuntu) packages_add libmhash-dev libmcrypt-dev libjpeg-dev zlib1g-dev;;
	esac

	# pwn: Build dependencies for cryptography

	case $ID in
		alpine) packages_add libffi-dev openssl-dev;;
		fedora) packages_add libffi-devel openssl-devel;;
		debian|ubuntu) packages_add libffi-dev libssl-dev;;
	esac

	# pwn: Dependencies for Ruby

	case $ID in
		alpine|debian|ubuntu) packages_add ruby;;
		fedora) packages_add ruby rubygems;;
	esac

	packages_install

	case $ID in
		alpine) download_rust && export PATH="$HOME/.cargo/bin:$PATH" && pip3 install --no-cache-dir --user pwntools;;
		*) pip3 install --no-cache-dir --user pwntools;;
	esac

	# pwn: Tools

	case $ID in
		alpine|fedora|debian|ubuntu|macos) packages_add radare2 testdisk socat nasm john binutils;;
	esac
	case $ID in
		alpine|fedora|debian|ubuntu) packages_add file squashfs-tools strace zip unzip p7zip;;
		macos) packages_add squashfs;;
	esac
	case $ID in
		alpine|macos) packages_add exiftool;;
		fedora) packages_add perl-Image-ExifTool;;
		debain|ubuntu) packages_add libimage-exiftool-perl;;
	esac
	case $ID in
		alpine|debian|ubuntu) packages_add netcat-openbsd;;
		fedora) packages_add netcat;;
	esac

	# pwn: Tools (Ruby)

	sudo gem install one_gadget

	# pwn: Tools (desktop)

	case $ID in
		alpine|fedora|debian|ubuntu) $desktop && download_cutter_re;;
		macos) $desktop && brew install --cask cutter;;
	esac

	# pwn: Final packages installation

	packages_install

fi
