#!/usr/bin/perl
###############################################################################
#                                                                             #
# IPFire.org - A linux based firewall                                         #
# Copyright (C) 2007-2015   IPFire Team   <info@ipfire.org>                   #
#                                                                             #
# This program is free software: you can redistribute it and/or modify        #
# it under the terms of the GNU General Public License as published by        #
# the Free Software Foundation, either version 3 of the License, or           #
# (at your option) any later version.                                         #
#                                                                             #
# This program is distributed in the hope that it will be useful,             #
# but WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               #
# GNU General Public License for more details.                                #
#                                                                             #
# You should have received a copy of the GNU General Public License           #
# along with this program.  If not, see <http://www.gnu.org/licenses/>.       #
#                                                                             #
###############################################################################

	### Clean up our environment
	#
	delete @ENV{qw(IFS CDPATH ENV BASH_ENV PATH)};
	$< = $>;

	# Store keys here
	$ENV{"GNUPGHOME"} = "/opt/pakfire/etc/.gnupg";

	require "/opt/pakfire/lib/functions.pl";
	
	my $interactive = 1;
	my $force = "noforce";
	
	&Pakfire::logger("PAKFIRE INFO: IPFire Pakfire $Conf::version started!");

	### Check if we are running as root
	#
	my $user = qx(whoami);
	chomp($user);
	unless ( "$user" eq "root" ) {
	  &Pakfire::message("PAKFIRE ERROR: You must run pakfire as user root!");
	  exit 1;
	}
	
	unless ( -e "/var/ipfire/red/active" ) {
		&Pakfire::message("PAKFIRE ERROR: You need to be online to run pakfire!");
		exit 2;
	}
	
	### Check if we are started by another name
	#
	if ( $0 =~ /pakfire-update$/ ) {
		&Pakfire::message("CRON INFO: Running an update");
		my $random = int(rand(60));
		&Pakfire::logger("CRON INFO: Waiting for $random seconds.");
		sleep($random);
		$ARGV[0] = "update";
		$interactive = 0;
	} elsif ( $0 =~ /pakfire-upgrade$/ ) {
		&Pakfire::message("CRON INFO: Running an upgrade");
		my $random = int(rand(3600));
		&Pakfire::logger("CRON INFO: Waiting for $random seconds.");
		sleep($random);
		$ARGV[0] = "upgrade";
		$interactive = 0;
	}
	
	unless (@ARGV) {
		&Pakfire::usage;
	}
	
	foreach (@ARGV) {
		if ("$_" =~ "^-") {
			# Turn off interactive mode
			$interactive = 0 if ("$_" eq "--non-interactive");
			$interactive = 0 if ("$_" eq "-y");
			
			# Turn off shell colors - Bad for displaying in webinterface
			$Pakfire::enable_colors = 0 if ("$_" eq "--no-colors");
			
			# Turn on force mode
			$force = "force" if ("$_" eq "-f" );
			$force = "force" if ("$_" eq "--force" );
		}
	}

	if ("$ARGV[0]" eq "install") {
		shift;
		
		### Make sure that the list is not outdated. 
		&Pakfire::dbgetlist("noforce");

		open(FILE, "<$Conf::dbdir/lists/packages_list.db");
		my @db = <FILE>;
		close(FILE);
		
		my $dep;
		my @deps;
		my $pak;
		my @paks;
		my @temp;
		my @templine;
		my $found = 0;
		my $return;
		my @all;
		foreach $pak (@ARGV) {
			unless ("$pak" =~ "^-") {
				$return = &Pakfire::isinstalled($pak);
				if ($return eq 0) {
					&Pakfire::message("PAKFIRE INFO: $pak is already installed");
					next; 
				}
				$found = 0;
				foreach (@db) {
					@templine = split(/;/,$_);
					if ("$templine[0]" eq "$pak" ) {
						push(@paks,$pak);
						push(@all,$pak);
						@temp = &Pakfire::resolvedeps("$pak");
						foreach $dep (@temp) {
							push(@deps,$dep) if $dep;
							push(@all,$dep) if $dep;
						}
						$found = 1;
						break;
					}
				}
				if ($found == 0) {
					&Pakfire::message("");
					&Pakfire::message("PAKFIRE WARN: The pak \"$pak\" is not known. Please try running \"pakfire update\".");
				}
			}
		}
		
		unless (@paks) {
			&Pakfire::message("PAKFIRE ERROR: No packages to install. Exiting...");
			exit 1;
		}

		if (@deps) {
			my %sort = map{ $_, 1 } @deps;
			@deps = keys %sort;
			&Pakfire::message("");
			&Pakfire::message("PAKFIRE INFO: Packages to install for dependencies:");
		}
		foreach $dep (@deps) {
		  my $size = &Pakfire::getsize("$dep");
			$size = &Pakfire::beautifysize($size);
		  &Pakfire::message("PAKFIRE INFO: $dep \t - $size");
		}

		&Pakfire::message("");
		&Pakfire::message("");
		&Pakfire::message("PAKFIRE INFO: Packages to install:");
		foreach $pak (@paks) {
		  my $size = &Pakfire::getsize("$pak");
			$size = &Pakfire::beautifysize($size);
		  &Pakfire::message("PAKFIRE INFO: $pak \t - $size");
		}
		
		my $totalsize;
		foreach $pak (@all) {
			$totalsize = ($totalsize + &Pakfire::getsize("$pak"));
		}
		$totalsize = &Pakfire::beautifysize($totalsize);
		&Pakfire::message("");
		&Pakfire::message("PAKFIRE INFO: Total size: \t ~ $totalsize");
		&Pakfire::message("");
		
		if ($interactive) {
		  &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]");
			my $ret = <STDIN>;
			chomp($ret);
			&Pakfire::logger("PAKFIRE INFO: Answer: $ret");
			if ( $ret ne "y" ) {
			  &Pakfire::message("PAKFIRE ERROR: Installation aborted.");
			  exit 1;
			}
		} else {
			&Pakfire::logger("PAKFIRE INFO: Interaction skipped.");
		}
		
#		my %sort = map{ $_, 1 } @all;
#		@all = sort keys %sort;

		### Download first
		foreach $pak (@all) {
			&Pakfire::getpak("$pak", "");
		}

		&Pakfire::message("");

		foreach $pak (@deps) {
			&Pakfire::setuppak("$pak") if ($pak ne "");
		}
		

		foreach $pak (@paks) {
			&Pakfire::setuppak("$pak") if ($pak ne "");
		}
		

	} elsif ("$ARGV[0]" eq "remove") {
		shift;
		
		my @paks;
		my $pak;
		foreach $pak (@ARGV) {
			unless ("$pak" =~ "^-") {
				$return = &Pakfire::isinstalled($pak);
				if ($return ne 0) {
					&Pakfire::message("PAKFIRE WARN: $pak is not installed");
					next;
				}
				push(@paks, $pak);
			}
		}
		
		unless (@paks) {
			&Pakfire::message("PAKFIRE ERROR: No packages to remove. Exiting...");
			exit 1;
		}
		
		&Pakfire::message("");
		&Pakfire::message("");
		&Pakfire::message("PAKFIRE INFO: Packages to remove:");
		foreach $pak (sort @paks) {
		  my $size = &Pakfire::getsize("$pak");
			$size = &Pakfire::beautifysize($size);
		  &Pakfire::message("PAKFIRE INFO: $pak \t - $size");
		}
		
		if ($interactive) {
		  &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]");
			my $ret = <STDIN>;
			chomp($ret);
			&Pakfire::logger("PAKFIRE INFO: Answer: $ret");
			if ( $ret ne "y" ) {
			  &Pakfire::message("PAKFIRE ERROR: Installation aborted.");
			  exit 1;
			}
		}
		
		foreach $pak (@paks) {
			&Pakfire::removepak("$pak");
		}
	
	
	} elsif ("$ARGV[0]" eq "update") {
		&Pakfire::makeuuid();
		&Pakfire::getmirrors("$force");
		&Pakfire::dbgetlist("$force");
		&Pakfire::getcoredb("$force");

	} elsif ("$ARGV[0]" eq "upgrade") {
		&Pakfire::upgradecore();
		my @upgradepaks = &Pakfire::dblist("upgrade", "noweb");
		my @deps = ();

		if (@upgradepaks) {
			# Resolve the dependencies of the to be upgraded packages
			@deps = &Pakfire::resolvedeps_recursive(@upgradepaks);

			&Pakfire::message("");
			&Pakfire::message("PAKFIRE UPGR: We are going to install all packages listed above.");
			if ($interactive) {
			  &Pakfire::message("PAKFIRE INFO: Is this okay? [y/N]");
				my $ret = <STDIN>;
				chomp($ret);
				&Pakfire::logger("PAKFIRE INFO: Answer: $ret");
				if ( $ret ne "y" ) {
				  &Pakfire::message("PAKFIRE ERROR: Installation aborted.");
				  exit 1;
				}
			}
		}
		
		# Download packages
		foreach $pak (@upgradepaks) {
			&Pakfire::getpak("$pak", "");
		}

		# Download dependencies
		foreach $pak (@deps) {
			&Pakfire::getpak("$pak", "");
		}

		# Install dependencies first
		foreach $pak (@deps) {
			&Pakfire::setuppak("$pak");
		}

		# Install all upgrades
		foreach $pak (@upgradepaks) {
			&Pakfire::upgradepak("$pak");
		}
		
	} elsif ("$ARGV[0]" eq "list") {
		if ("$ARGV[1]" =~ /installed|notinstalled/) {
			&Pakfire::dblist("$ARGV[1]", "noweb");
		} else {
			&Pakfire::message("PAKFIRE WARN: Not a known option $ARGV[1]") if ($ARGV[1]); 
			&Pakfire::dblist("all", "noweb");
		}
		
	} elsif ("$ARGV[0]" eq "resolvedeps") {
		foreach (@ARGV) {
			next if ("$_" eq "resolvedeps");
			next if ("$_" =~ "^-");
			&Pakfire::resolvedeps("$_");
		}
	} elsif ("$ARGV[0]" eq "enable") {
		if ("$ARGV[1]" eq "updates") {
			system("ln -s ../../opt/pakfire/pakfire /etc/fcron.daily/pakfire-update");
		} elsif ("$ARGV[1]" eq "upgrades") {
			system("ln -s ../../opt/pakfire/pakfire /etc/fcron.daily/pakfire-upgrade");
		}
	} elsif ("$ARGV[0]" eq "disable") {
		if ("$ARGV[1]" eq "updates") {
			system("rm -f /etc/fcron.daily/pakfire-update");
		} elsif ("$ARGV[1]" eq "upgrades") {
			system("rm -f /etc/fcron.daily/pakfire-upgrade");
		}
	} elsif ("$ARGV[0]" eq "status") {
		&Pakfire::status;
	} else {
		&Pakfire::usage;
	}

	&Pakfire::logger("PAKFIRE INFO: Pakfire has finished. Closing.");

	exit 0;
