use v5.10;
use strict;

use lib ('e:/scripts/perl/various/convertjpegaux');
use helpers qw(sec std_time std_time_int);

use Getopt::Long;
Getopt::Long::Configure('bundling');

my %params = (
	sparse => undef,
	auto_threshold => 180,
	auto_power => 1/2.0,
	auto_tt => 10,
	auto_tt_power => 1/3.0,

	agent => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', 
	url => undef, title => undef, ext => 'mp4', start => undef, end => undef, dry_run => 0, NN => 3, TT => 30, offset => 0,
	
	drop_headers => 0,
	info_only => 0,
);

GetOptions(
	'sparse=s' => \$params{sparse},
	'auto-threshold=i' => \$params{auto_threshold},
	'auto-power=s' => \$params{auto_power},
	'auto-tt=i' => \$params{auto_tt},
	'auto-tt-power=s' => \$params{auto_tt_power},

	'agent=s' => \$params{agent}, 
	'url=s' => \$params{url}, 
	'title=s' => \$params{title}, 
	'ext=s' => \$params{ext}, 
	'start=s' => \$params{start}, 
	'end=s' => \$params{end},
	'dry-run=i' => \$params{dry_run},
	'NN=s' => \$params{NN},
	'TT=s' => \$params{TT},
	'offset=i' => \$params{offset},
	
	'drop-headers' => \$params{drop_headers},
	'info-only' => \$params{info_only},
)
or die 'GetOptions';

$params{title} =~ s/:/_/g;
$params{title} =~ s/\|/\@/g;
$params{title} =~ s/, #.*//;

say ''; say "REM --- $_=$params{$_}" for sort keys %params; say '';

my $n_tries = 1;
my $sleep_after_load = 5.0;
my $seg_size_limit = 1.0 * 2**10;


my $headers = $params{drop_headers}
	? "User-Agent: $params{agent}\r\n"
	: (join "\r\n", "User-Agent: $params{agent}", map {/#--- (.+)/ ? $1 : ()} <DATA>) . "\r\n"
;

sub get_duration {
	my $cmd = qq(ffprobe-64 -hide_banner -headers "$headers" -i "$params{url}");

	use Capture::Tiny ':all';
	$_ = capture_stderr {system $cmd};

	my ($dur) = /Duration: ([:\d\.]+)/;
	my ($br) = /bitrate: (\S+)/;
	my ($res) = /Video: .+? (\d{3,4}x\d+)/;

	die if ! defined($dur);
	
	say qq `$params{title} duration: $dur bitrate: $br res: $res`;
	$dur;
}

sub mod_title {
	my $title_mod = defined $params{start} ? "$params{title}.ss=@{[std_time_int(sec($params{start}))]}" : $params{title};
	$title_mod = defined $params{end} ? "$title_mod.t=@{[std_time_int(sec($params{end}) - (sec($params{start} or 0)))]}" : $title_mod;
	$title_mod =~ s/:/_/g;
	$title_mod;
}

sub out_fn {my $title_mod = mod_title(); qq($title_mod.$params{ext})}

sub load {
	my $output_fn = out_fn();
	die if -e $output_fn;
	
	my $ss = $params{start} ? "-ss $params{start}" : '';
	my $t = $params{end} ? '-t ' . std_time_int(sec($params{end}) - (sec($params{start} or 0))) : '';
	my $cmd = qq `ffmpeg-64 -hide_banner -analyzeduration 10M -reconnect 1 -icy 0 -headers "$headers" $ss $t -i "$params{url}" -c copy -n -- "$output_fn"`;
	say "!!!--- $cmd";
	exit if $params{info_only};

	for (my $count = $n_tries; $count--; sleep $sleep_after_load) {
		system $cmd; 
		last if (-s $output_fn) > $seg_size_limit;
	}
	if ((-s $output_fn) < $seg_size_limit) {unlink $output_fn; die}
}

sub check_range {
	my $t = eval $_[0];
	defined $t && ($t >= 0 && $t <= 1);
}

if ($params{dry_run} == 0 && (check_range($params{start}) || check_range($params{end}))) {
	my $dur = sec get_duration;
	$params{start} = std_time_int($dur * eval $params{start});
	$params{end} = std_time_int($dur * eval $params{end});
}
else {
	$params{start} && ($params{start} = std_time_int(sec $params{start}));
	$params{end} && ($params{end} = std_time_int(sec $params{end}));
}

say "****** params{start}= $params{start}";
say "****** params{end}= $params{end}";

if ($params{dry_run} == 0) {load()}
else {
	die if -e "$params{title}" or -e "$params{title}.7z" or -e "$params{title}.$params{ext}";
	die if !defined($params{NN}) or !defined($params{TT});
	$params{NN} = eval $params{NN};
	$params{TT} = sec($params{TT});
	
	my $dur = get_duration;
	
	if ($params{sparse}) {
		if ($params{sparse} eq 'auto') {
			my $tx = sec($dur);
			my ($X1, $Y1, $P) = ($params{auto_threshold}, $params{auto_threshold}*0.5, eval $params{auto_power}); ###   1/1.73); 
			my $ty = ($Y1 / $X1 ** $P) * ($tx ** $P);
			use Math::Round;
			$params{sparse} = round $tx / $ty;
			$params{sparse} = 1 if $params{sparse} < 1;
			print "====== calculated sparse: $params{sparse}\n";
			$params{TT} = sprintf '%1.2f', $params{auto_tt} * ($tx / $params{auto_threshold}) ** (eval $params{auto_tt_power});
			print "====== calculated TT: $params{TT}\n";
		}

		if ($params{sparse} < 2) {
			print "====== params{sparse} < 2, force single download\n";	
			undef $params{start};
			undef $params{end};
			load;
			exit;
		}

		$params{NN} = int sec($dur) / $params{TT} / $params{sparse};
	}

	print "====== NN: $params{NN} TT: $params{TT} sparse: $params{sparse}\n";
	exit if $params{info_only};
	exit if $params{NN} == 0;
	
	$params{start} = 0 unless $params{start};
	$params{end} = $dur unless $params{end};
	$params{end} = $dur if sec($params{end}) > sec($dur);
	my $start = sec($params{start});
	my $end = sec($params{end});
	
	my $dir = mod_title();
	die if -e $dir;
	system qq(md "$dir");	

	for (my ($c, $i) = ('001', 1); $i <= $params{NN}; ++$c, ++$i, sleep 1) {
		my $s = $start + ($end - $start) / (1 + $params{NN}) * $i + $params{offset};
		my $e = $s + $params{TT};

		say "=== $params{start} $params{end} $s $e";
		($params{start}) = (std_time_int $s) =~ /(\d\d:\d\d:\d\d)/;
		($params{end}) = (std_time_int $e) =~ /(\d\d:\d\d:\d\d)/;
		say "=== $params{start} $params{end}";

		my $frag = out_fn();
		load() unless -e $frag;
		system qq (move "$frag" "$dir"\\"$c   $frag");
	}
}




__DATA__

#--- Accept: */*
#--- Accept-Encoding: identity;q=1, *;q=0
#--- Accept-Language: en-US,en;q=0.9,ru;q=0.8
#--- Cache-Control: max-age=0
#--- Priority: u=0, i
#--- Sec-Ch-Ua: \"Chromium\";v=\"142\", \"Google Chrome\";v=\"142\", \"Not_A Brand\";v=\"99\"
#--- Sec-Ch-Ua-Arch: \"x86\"
#--- Sec-Ch-Ua-Bitness: \"64\"
#--- Sec-Ch-Ua-Full-Version: \"142.0.7444.177\"
#--- Sec-Ch-Ua-Full-Version-List: \"Chromium\";v=\"142.0.7444.177\", \"Google Chrome\";v=\"142.0.7444.177\", \"Not_A Brand\";v=\"99.0.0.0\"
#--- Sec-Ch-Ua-Mobile: ?0
#--- Sec-Ch-Ua-Platform: \"Windows\"
#--- Sec-Ch-Ua-Platform-Version: \"10.0.0\"
#--- Sec-Fetch-Dest: document
#--- Sec-Fetch-Mode: navigate
#--- Sec-Fetch-Site: none
#--- Sec-Fetch-User: ?1
#--- Upgrade-Insecure-Requests: 1


:authority: livecamrips.to
:method: GET
:path: /video/11101782
:scheme: https
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9,ru;q=0.8
Cache-Control: max-age=0
Priority: u=0, i
Sec-Ch-Ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"
Sec-Ch-Ua-Arch: "x86"
Sec-Ch-Ua-Bitness: "64"
Sec-Ch-Ua-Full-Version: "142.0.7444.177"
Sec-Ch-Ua-Full-Version-List: "Chromium";v="142.0.7444.177", "Google Chrome";v="142.0.7444.177", "Not_A Brand";v="99.0.0.0"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Model: ""
Sec-Ch-Ua-Platform: "Windows"
Sec-Ch-Ua-Platform-Version: "10.0.0"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36
