#!/usr/bin/perl -w
###############################################################################
#    Copyright (C) 2004 by Eric Gerbier
#    Bug reports to: gerbier@users.sourceforge.net
#    $Id: Makefile.pl 1174 2008-09-12 09:50:03Z gerbier $
#
#    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 2 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.
#
#################################################################################
# a perl script to check for module requirements, needed by afick on tar.gz intall
# to build the makefile
#################################################################################

use strict;
use warnings;

#use diagnostics;
use English '-no_match_vars';

my %cache;    # a cache to avoid test and display same module many times

my $failed_modules = q{};
#################################################################################
# search in a perl file for required module (with 'use' keyword)
# and check if available
sub check_module($$) {
	my $fic  = shift @_;
	my $text = shift @_;

	print "search required perl modules for $text ($fic) :\n";
	my $retcode = 0;

	my $fh;    # file handle
	## no critic (RequireBriefOpen)
	if ( open $fh, '<', $fic ) {

		my $nb_ko = 0;    # number of failed modules
	  MOD: while (<$fh>) {

			# search for 'use' keyword
			# I suppose 'require' keywords are used with eval
			if ( $_ =~ m/^use\s+([^\s;(]*)/ ) {

				# get the name without any import list
				my $module = $1;

				if ( exists $cache{$module} ) {
					$nb_ko += $cache{$module};
					next MOD;
				}

				#change tree structure to directories
				my $module_dir = $module;
				$module_dir =~ s/::/\//;

				# now test
				eval { require $module_dir . '.pm' };
				if ($EVAL_ERROR) {

					$cache{$module} = 1;
					$failed_modules .= "$module ";

					# we do not test the error message
					print "  WARNING : perl module $module not found\n";
					$nb_ko++;
				}
				else {
					$cache{$module} = 0;
					print "  OK : found perl module $module\n";
				}
			}
		}
		close $fh or warn "impossible to close $fic : $ERRNO\n";

		if ( $nb_ko == 0 ) {
			print "OK : you can install $text\n";
			$retcode = 1;
		}
		else {
			warn "WARNING : you can not install $text\n";
			$retcode = 0;
		}
	}
	else {
		warn "WARNING : impossible to open $fic : $ERRNO\n";
		$retcode = 0;
	}
	print "----------------------------------------\n";
	return $retcode;
}
#################################################################################
# change perl path (shebang) for all perl scripts (*.pl)
sub change_header($$) {
	my $old = shift @_;    # old perl path
	my $new = shift @_;    # new perl path

	# get all perl script
	my @list = glob '*.pl';
  SCRIPT: foreach my $fic (@list) {
		print "$fic\n";
		rename $fic, $fic . '.sav';
		## no critic (RequireBriefOpen)
		my $fh_old;
		if ( !open $fh_old, '<', $fic . '.sav' ) {
			warn "can not open  $fic.sav : $ERRNO\n";
			next SCRIPT;
		}
		my $fh_new;
		if ( !open $fh_new, '>', $fic ) {
			warn "can not open  $fic : $ERRNO\n";
			next SCRIPT;
		}

		my $nbline = 0;    # test for first line
		while (<$fh_old>) {
			if ( $nbline == 0 ) {

				# we change only the first script line
				## no critic (ProhibitNoisyQuotes)
				print {$fh_new} '#!' . $new . " -w\n";
			}
			else {
				print {$fh_new} $_;
			}
			$nbline++;
		}

		close $fh_old or warn "can not close $fic.sav : $ERRNO\n";
		close $fh_new or warn "can not close  $fic : $ERRNO\n";
	}
	chmod oct(755), @list;
	return;
}
#################################################################################
# search in PATH for a command, and return full path
# avoid to use the which unix command, or the shell builtin :type --path
sub search_cmd($) {
	my $prog = shift @_;

	foreach ( split /:/, $ENV{PATH} ) {
		if ( -x "$_/$prog" ) {
			return "$_/$prog";
		}
	}
	return;
}
#################################################################################
#			main
#################################################################################

# search and configure perl path
################################
my $perlpath = search_cmd('perl');

# only change perl path if not (linux) standard
if ( $perlpath ne '/usr/bin/perl' ) {
	change_header( '/usr/bin/perl', $perlpath );
}

# check for needed modules
# we only check the main programs : afick and afick-tk
# todo ? : check all others perl scripts ?
# ################################
if ( check_module( 'afick.pl', 'afick core' ) ) {

	# ok : "prepare" makefile for install
	rename 'Makefile.in', 'makefile';
	if ( check_module( 'afick-tk.pl', 'afick gui' ) ) {

		# all is ok
		print "you can run 'make all' to install afick core and gui\n";
	}
	else {

		# gui can be installed
		print "you can run 'make install' to install afick core\n";
		print
"  if you want to install the afick gui, you have to install first the perl modules : $failed_modules\n";
	}
}
else {

	# no install possible
	warn "ERROR : you can not install any afick component\n";
	warn "  you have to install the missing perl modules : $failed_modules\n";
}
