#!/usr/local/bin/perl

#
# Authentic Theme (https://github.com/authentic-theme/authentic-theme)
# Copyright Ilia Rostovtsev <ilia@virtualmin.com>
# Licensed under MIT (https://github.com/authentic-theme/authentic-theme/blob/master/LICENSE)
#
use strict;

our (
	%in, %text, %gconfig,
	%request_uri, %userconfig, @allowed_paths,
	@remote_user_info, $cwd, $path
);

require($ENV{'THEME_ROOT'}."/extensions/file-manager/file-manager-lib.pl");

kill_previous($0, $$);

my %data;
my @list;
my @items;
my $auto_orient = " -auto-orient";
my $width = int($in{'width'});
my $height = int($in{'height'});
my $file_requested = $in{'file_requested'};
my $files_all = $in{'files_all'};
my $files_selected = $in{'files_selected'};
my $search = $in{'query'};

# Use only current file or read list of files
if (!$files_all) {
	@list = ($file_requested);
	if ($files_selected) {
		@list = split(/\0/, $in{'name'});
		}
	}
else {
	if ($search) {
		@list = exec_search();
		}
	else {
		unless (opendir(DIR, $cwd)) {
			print_error(
				"$text{'theme_xhred_global_error'}: [tt]`$cwd`[/tt]- $!."
			);
			exit;
			}
		@list = grep { $_ ne '.' && $_ ne '..' } readdir(DIR);
		closedir(DIR);
		}

	my $page = 1;
	my $pagelimit = 4294967295;
	my $pages = 0;

	my $max_allowed = int($userconfig{'max_allowed'});
	if ($max_allowed !~ /^[0-9,.E]+$/ || $max_allowed < 100 || $max_allowed > 10000)
	{
		$max_allowed = 1000;
		}

	my $totals = scalar(@list);
	my $totals_spliced = $totals;

	my $tuconfig_per_page =
	    get_user_config('config_portable_module_filemanager_records_per_page');

	if (server_pagination_enabled($totals, $max_allowed, $search)) {
		$page = int($in{'page'}) || 1;
		$pagelimit = int($in{'paginate'}) || int($tuconfig_per_page) || 30;
		$pages = ceil(($totals) / $pagelimit);
		if ($page > $pages) {
			$page = $pages;
			$in{'page'} = $page;
			}
		my $splice_start = $pagelimit * ($page - 1);
		my $splice_end = $pagelimit;

		@list = sort { $a cmp $b } @list;
		@list = splice(@list, $splice_start, $splice_end);
		$totals_spliced = scalar(@list);
		}
	}

# Leave only allowed
if (test_allowed_paths()) {
	my @tmp_list;
	for $path (@allowed_paths) {
		my $slashed = $path;
		$slashed .= "/" if ($slashed !~ /\/$/);
		push @tmp_list, grep {
			string_starts_with($slashed, "$cwd/$_/") ||
			    index($slashed, $_) != -1 ||
			    index("$cwd/$_", $slashed) != -1
			    } @list;
		}
	my %hash = map { $_, 1 } @tmp_list;
	@list = keys %hash;
	}

my @checked_list;
foreach my $filename (@list) {
	$filename = fm_normalize_path_name($filename, $cwd);
	my $file = fm_checked_cwd_path($filename);
	if (!$file) {
		print_error(fm_not_allowed_error($filename)) if (!$files_all);
		next;
		}
	push(@checked_list, [$filename, $file]);
	}

my $index = 0;
my $index_requested = 0;
if (has_command('identify')) {
	foreach my $entry (@checked_list) {
		my ($filename, $file) = @$entry;
		my $type = mimetype($file);
		my $files_size = -s $file;
		my $file_encoded;
		my $processed = 0;
		my ($w, $h, $o) = (0, 0, undef);

		if (string_starts_with($type, 'image')) {

			if ($files_all ||
				$files_selected ||
				$file_requested eq $filename)
			{

				my $data_auto =
				    ($auto_orient ? '%w %h %[orientation]' : '%w %h');
				my $data =
				    `identify -ping -format '$data_auto' @{[quotemeta($file)]}`;
				($w, $h, $o) =
				    $data =~ /(?|(\d+)\s(\d+)\s(\w+)|(\d+)\s(\d+))/;
				my $orientation = ($w > $h ? $w : $h);
				my $factor = ($w > $h ? $width : $height);
				my $types_excluded = (string_contains($type, 'svg') ||
					    string_contains($type, 'microsoft.icon'));

				if ($w && $h) {

# Process image in case it's larger than 600kb or its dimensions larger than user's screen resolution
					if (
						!$types_excluded &&
						($orientation > $factor ||
							$files_size > 600000)
					    )
					{

						# Fix orientation sizes
						if ($auto_orient && $o) {
							if (
								string_starts_with($o,
									'Left') ||
								string_starts_with($o,
									'Right'))
							{
								my $w_ = $w;
								my $h_ = $h;
								$h = $w_;
								$w = $h_;
								}
							}

						# Extract smaller version of the file
						my $file_out = "$file.bak~";
						my $convert_size = (
							($w > $h ? undef : 'x').
							    (     $orientation > $factor
								? $factor
								: $orientation)
						);
						system(
							"convert -quality 60% -resize $convert_size @{[quotemeta($file)]} $auto_orient @{[quotemeta($file_out)]}"
						);

						# Store smaller version data
						$file_encoded = encode_base64(
							read_file_contents($file_out));
						if ($orientation > $factor) {
							$h = int($factor / ($w / $h));
							$w = $factor;
							}

						# Remove temporary file
						unlink_file($file_out);

						$processed++;
						}
					else {
						$file_encoded = encode_base64(
							read_file_contents($file));
						}

					}

				if ($file_requested eq $filename) {
					$index_requested = $index;
					}
				}

			if ($file_encoded) {
				push(
					@items,
					{
						index => $index,
						title => html_escape(
							"$filename (@{[theme_nice_size_local($files_size, -1)]})"
						),
						file => $filename,
						cwd => $cwd,
						src => (
							"data:$type;base64,$file_encoded"
						),
						p => $processed,
						w => int($w),
						h => int($h),
					}
				);
				$index++;
				}
			}
		}
	if (@items) {
		$data{'items'} = \@items;
		$data{'index_requested'} = $index_requested;
		}
	else {
		$data{'warning'} =
		    $text{'theme_xhred_filemanager_preview_images_error'};
		}
	}
else {

	# Let user install ImageMagick in single click
	$data{'error'} = $text{'theme_xhred_filemanager_preview_images_deps_error1'};
	my $package_updates = "package-updates";
	if (foreign_available($package_updates)) {
		my $redir = "../$request_uri{'module'}";
		my $pkgname =
		    ($gconfig{'os_type'} =~ /debian/ ? 'imagemagick' : 'ImageMagick');
		my %package_updates_lang = load_language($package_updates);
		my $update_failed = html_escape($package_updates_lang{'update_failed'});
		my $update_ok =
		    html_escape(text('global_deps_installed', "<code>$pkgname</code>"));
		my $update_error =
		    html_escape(text('global_deps_error', "<kbd>$pkgname</kbd>"));
		my $installing_text = html_escape(
			text('global_deps_installing', "<code>$pkgname</code>"));
		my $install_link =
		    "../$package_updates/update.cgi?source=3&confirm=1&mode=new&u=$pkgname&redir=$redir&redirdesc=File%20Manager&xnavigation=1";
		$data{'error'} .= " ".
		    text(
			'theme_xhred_filemanager_preview_images_deps_error2',
			ui_link(
				'javascript:;',
				$text{'theme_xhred_global_click_here'},
				'text-darker',
				" nref onclick='fm_install_deps(\"$install_link\", [\"$update_failed\", \"$update_ok\", \"$update_error\", \"$installing_text\"], this)'"
			)
		    );
		}
	}

print_json([\%data]);
