#!/usr/local/bin/perl

use strict;
use warnings;
use Capture::Tiny qw(capture);
use WWW::Curl::Easy;

use constant {
	SXHKD_PATH			=> '/usr/local/bin/sxhkd',
	PGREP_PATH			=> '/bin/pgrep',
	PKILL_PATH			=> '/bin/pkill',
	XRANDR_PATH			=> '/usr/local/bin/xrandr',
	MAINSCREEN_PATH		=> '/usr/home/jozan/.local/bin/mainscreen',
	DUALSCREEN_PATH		=> '/usr/home/jozan/.local/bin/dualscreen',
	TRIPLESCREEN_PATH	=> '/usr/home/jozan/.local/bin/triplescreen',
	BSPC_PATH			=> '/usr/local/bin/bspc',
	COMPTON_PATH		=> '/usr/local/bin/compton',
	FEH_PATH			=> '/usr/local/bin/feh',
	XSET_PATH			=> '/usr/local/bin/xset',
	SETXKBMAP_PATH		=> '/usr/local/bin/setxkbmap',
	DUNST_PATH			=> '/usr/local/bin/dunst',
	LOWBAT_PATH			=> '/usr/local/bin/lowbat',
	EMACS_PATH			=> '/usr/local/bin/emacs',
	ALACRITTY_PATH		=> '/usr/local/bin/alacritty',
	SH_PATH				=> '/bin/sh',
	ZSH_PATH			=> '/usr/local/bin/zsh',
	COWSAY_PATH			=> '/usr/local/bin/cowsay',
	ESPEAK_PATH			=> '/usr/local/bin/espeak',
	HTOP_PATH			=> '/usr/local/bin/htop',
	GOTOP_PATH			=> '/usr/local/bin/gotop',
	VIFM_PATH			=> '/usr/local/bin/vifm',
	GIT_PATH			=> '/usr/local/bin/git',
	QTOX_PATH			=> '/usr/local/bin/qtox'
};
use constant {
	BSP_BORDER_WIDTH		=> 1,
	BSP_WINDOW_GAP			=> 0,
	BSP_BORDER_COLOR		=> '#b92121',
	BSP_SPLIT_RATIO			=> '0.50',
	BSP_BORDERLESS_MONOCLE	=> 'true',
	BSP_GAPLESS_MONOCLE		=> 'true',
	BSP_SINGLE_MONOCLE		=> 'true',
	XSET_R_RATE_DELAY		=> 200,
	XSET_R_RATE_RATE		=> 100,
};
use constant WALLPAPER_PATH		=> '/usr/home/jozan/Pictures/wallpaper.jpg';
use constant COWSAY_WELCOME		=> 'Welcome back, partner! And remember to try glest!';
use constant NETWORK_TEST_URL	=> 'https://freebsd.org/';

sub run_if_dead
{
	my @argv = @_;
	my $bin;
	my $pid;

	$bin = $argv[0];
	$bin =~ s/.+\///g;
	my (undef, undef, $retval) = capture {
		system(
			PGREP_PATH,
			$bin
			);
	};
	$retval = ($retval >> 8) & 0xff;
	if ($retval != 0) {
		$pid = fork();
		if (not $pid) {
			exec(@argv);
			exit;
		}
	}
	return;
}

sub kill_some
{
	system(PKILL_PATH, 'alacritty');
	return;
}

sub enable_screens
{
	my $stdout;
	my $screens;
	
	$screens = 1;
	($stdout, undef, undef) = capture {
		system(XRANDR_PATH);
	};
	if ($stdout =~ m/HDMI1 connected/ && $stdout =~ m/VGA1 connected/ == 1) {
		$screens = 3;
		system(TRIPLESCREEN_PATH);
	}
	elsif ($stdout =~ m/DP1 connected/) {
		$screens = 2;
		system(DUALSCREEN_PATH);
	}
	else {
		system(MAINSCREEN_PATH);
	}
	return $screens;
}

sub bspc_configs
{
	system(BSPC_PATH, 'config', 'border_width',			BSP_BORDER_WIDTH);
	system(BSPC_PATH, 'config', 'window_gap',			BSP_WINDOW_GAP);
	system(BSPC_PATH, 'config', 'focused_border_color',	BSP_BORDER_COLOR);
	system(BSPC_PATH, 'config', 'split_ratio',			BSP_SPLIT_RATIO);
	system(BSPC_PATH, 'config', 'borderless_monocle',	BSP_BORDERLESS_MONOCLE);
	system(BSPC_PATH, 'config', 'gapless_monocle',		BSP_GAPLESS_MONOCLE);
	system(BSPC_PATH, 'config', 'single_monocle',		BSP_SINGLE_MONOCLE);
	return;
}

sub bspc_rules
{
	system(BSPC_PATH, 'rule', '-a', 'Emacs',			'state=tiled');
	system(BSPC_PATH, 'rule', '-a', 'Firefox',			'desktop=08', 'follow=true');
	system(BSPC_PATH, 'rule', '-a', 'Wine',				'desktop=07', 'state=floating');
	system(BSPC_PATH, 'rule', '-a', 'Dunst',			'layer=above');
	system(BSPC_PATH, 'rule', '-a', 'Zathura',			'state=tiled');
	system(BSPC_PATH, 'rule', '-a', 'qTox',				'desktop=12');
	system(BSPC_PATH, 'rule', '-a', 'DergodsRealmII',	'state=floating');
	system(BSPC_PATH, 'rule', '-a', 'obs',				'desktop=12', 'follow=true');
	return;
}

sub run_bg_programs
{
	my ($screens) = @_;

	run_if_dead(SXHKD_PATH);
	run_if_dead(COMPTON_PATH);
	run_if_dead(DUNST_PATH);
	run_if_dead(LOWBAT_PATH);
	if ($screens > 1) {
		system(FEH_PATH, '--bg-fill', WALLPAPER_PATH, '--bg-fill', WALLPAPER_PATH);
	}
	else {
		system(FEH_PATH, '--bg-fill', WALLPAPER_PATH);
	}
	system(XSET_PATH, 'r', 'rate', XSET_R_RATE_DELAY, XSET_R_RATE_RATE);
	system(SETXKBMAP_PATH, '-layout', 'us,fr', '-option', 'grp:alt_shift_toggle');
	return;
}

sub fg_on_three_screens
{
	my @term_pid;

	$term_pid[0] = fork();
	if (not $term_pid[0]) {
		exec(
			ALACRITTY_PATH, '-e', SH_PATH, '-c',
			COWSAY_PATH . ' "' . COWSAY_WELCOME . '"; ' . ZSH_PATH
			);
		exit;
	}
	sleep(1);
	$term_pid[1] = fork();
	if (not $term_pid[1]) {
		exec(ALACRITTY_PATH, '-e', HTOP_PATH);
		exit;
	}
	sleep(1);
	$term_pid[2] = fork();
	if (not $term_pid[2]) {
		exec(ALACRITTY_PATH, '-e', GOTOP_PATH);
		exit;
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-f', 'west');
	$term_pid[3] = fork();
	if (not $term_pid[3]) {
		exec(ALACRITTY_PATH, '-e', VIFM_PATH);
		exit;
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-z', 'right', '180', '0');
	system(BSPC_PATH, 'node', '-z', 'top', '0', '70');
	system(BSPC_PATH, 'node', '-f', 'east');
	system(BSPC_PATH, 'node', '-f', 'north');
	system(BSPC_PATH, 'node', '-z', 'bottom', '0', '-280');
	system(BSPC_PATH, 'node', '-f', 'north');
	system(BSPC_PATH, 'node', '-f', 'west');
	return;
}

sub fg_on_two_screens
{
	my @term_pid;

	$term_pid[0] = fork();
	if (not $term_pid[0]) {
		exec(
			ALACRITTY_PATH, '-e', SH_PATH, '-c',
			COWSAY_PATH . ' "' . COWSAY_WELCOME . '"; ' . ZSH_PATH
			);
		exit;
	}
	sleep(1);
	$term_pid[1] = fork();
	if (not $term_pid[1]) {
		exec(ALACRITTY_PATH, '-e', HTOP_PATH);
		exit;
	}
	sleep(1);
	$term_pid[2] = fork();
	if (not $term_pid[2]) {
		exec(ALACRITTY_PATH, '-e', GOTOP_PATH);
		exit;
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-f', 'west');
	$term_pid[3] = fork();
	if (not $term_pid[3]) {
		exec(ALACRITTY_PATH, '-e', VIFM_PATH);
		exit;
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-z', 'right', '180', '0');
	system(BSPC_PATH, 'node', '-z', 'top', '0', '70');
	system(BSPC_PATH, 'node', '-f', 'east');
	system(BSPC_PATH, 'node', '-f', 'north');
	system(BSPC_PATH, 'node', '-z', 'bottom', '0', '-280');
	system(BSPC_PATH, 'node', '-f', 'north');
	system(BSPC_PATH, 'node', '-f', 'west');
	return;
}

sub fg_on_one_screen
{
	my @term_pid;

	$term_pid[0] = fork();
	if (not $term_pid[0]) {
		exec(
			ALACRITTY_PATH, '-e', SH_PATH, '-c',
			COWSAY_PATH . ' "' . COWSAY_WELCOME . '"; ' . ZSH_PATH
			);
		exit;
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-p', 'west');
	$term_pid[1] = fork();
	if (not $term_pid[1]) {
		exec(ALACRITTY_PATH, '-e', HTOP_PATH);
		exit;
	}
	sleep(1);
	$term_pid[2] = fork();
	if (not $term_pid[2]) {
		exec(ALACRITTY_PATH, '-e', GOTOP_PATH);
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-f', 'east');
	$term_pid[3] = fork();
	if (not $term_pid[3]) {
		exec(ALACRITTY_PATH, '-e', VIFM_PATH);
	}
	sleep(1);
	system(BSPC_PATH, 'node', '-f', 'west');
	system(BSPC_PATH, 'node', '-f', 'north');
	system(BSPC_PATH, 'node', '-z', 'bottom', '0', '-200');
	system(BSPC_PATH, 'node', '-z', 'right', '-220', '0');
	system(BSPC_PATH, 'node', '-f', 'east');
	system(BSPC_PATH, 'node', '-z', 'bottom', '0', '70');
	system(BSPC_PATH, 'node', '-f', 'north');
	return;
}

sub run_fg_programs
{
	my ($screens) = @_;
	my $espeak_pid;

	system(BSPC_PATH, 'desktop', '-f', '01');
	run_if_dead(EMACS_PATH);
	sleep(12);
	system(BSPC_PATH, 'desktop', '-f', '09');
	$espeak_pid = fork();
	if (not $espeak_pid) {
		exec(ESPEAK_PATH, COWSAY_WELCOME);
	}
	if ($screens == 3) {
		fg_on_three_screens();
	}
	elsif ($screens == 2) {
		fg_on_two_screens();
	}
	else {
		fg_on_one_screen();
	}
	return;
}

sub run_network_programs
{
	my $curl;
	my $response_body;
	my $retval;

	$curl = WWW::Curl::Easy->new;
	$curl->setopt(CURLOPT_URL, NETWORK_TEST_URL);
	$curl->setopt(CURLOPT_WRITEDATA, \$response_body);
	$retval = $curl->perform;
	if ($retval == 0) {
		system(GIT_PATH, '-C', '/usr/home/jozan/.elfeed', 'pull', 'origin', 'master');
		run_if_dead(QTOX_PATH);
	}
	return;
}

sub main
{
	my $screens;

	kill_some();
	$screens = enable_screens();
	bspc_configs();
	bspc_rules();
	run_bg_programs($screens);
	run_fg_programs($screens);
	run_network_programs();
	return;
}

main();

__END__