#!/usr/bin/perl

############################################################################
# This file is part of FreeFem++.                                          #
#                                                                          #
# FreeFem++ is free software: you can redistribute it and/or modify        #
# it under the terms of the GNU Lesser General Public License as           #
# published by the Free Software Foundation, either version 3 of           #
# the License, or (at your option) any later version.                      #
#                                                                          #
# FreeFem++ 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 Lesser General Public License for more details.                      #
#                                                                          #
# You should have received a copy of the GNU Lesser General Public License #
# along with FreeFem++. If not, see <http://www.gnu.org/licenses/>.        #
############################################################################
# SUMMARY : Download third-party packages independently of FF configuration
# LICENSE : LGPLv3
# ORG     : LJLL Universite Pierre et Marie Curie, Paris, FRANCE
# AUTHORS : Antoine Le Hyaric
# E-MAIL  : http://www.ljll.math.upmc.fr/lehyaric

use strict;
use Getopt::Std;
use Digest::MD5 qw(md5_hex); # [[http://perldoc.perl.org/Digest/MD5.html]]

# This download script needs to be able to work on platforms that do not have threads (eg Mingw).

my $can_use_threads=eval 'use threads;use threads::shared;1';

my %opts;
getopts('afho:',\%opts);

if($opts{h}){
	print <<EOF;
getall [options]: Download third-party packages independently of the FreeFem++ configuration procedure

Available options:

-a = accept all licences without further user interaction
-f = force downloads even if packages are already present locally
-h = this help
-o name,name,... = only download packages with the given names

EOF
	exit 0;
}

# Accumulate errors and print them all at the end of the script

my $errors='';
if($can_use_threads){share(\$errors)}

# Accumulate errors and print them all at the end of the script

my $errors='';
if($can_use_threads){share(\$errors)}

# list required packages
my $only=0;
my %packs;
if(defined $opts{o}){
	$only=1;
	foreach(split(/,/,$opts{o})){$packs{$_}=1}
}

# can be run from the parent directory

if(-x "download/getall"){chdir "download"}

# can be run from any of the child directories

if(-x "../getall"){chdir ".."}

system "mkdir -p pkg";
my @downloads;

download('ARPACK','http://www.caam.rice.edu/software/ARPACK/SRC/arpack96.tar.gz',
 	'http://www.caam.rice.edu/software/ARPACK',
	'arpack96.tar.gz',
	'fffaa970198b285676f4156cebc8626e');
download('ARPACK','http://www.caam.rice.edu/software/ARPACK/SRC/patch.tar.gz',
	'http://www.caam.rice.edu/software/ARPACK',
	'patch.tar.gz',
	'14830d758f195f272b8594a493501fa2');
download('BLAS','http://www.netlib.org/blas/blas-3.7.1.tgz',
	'http://www.netlib.org/blas',
	'blas-3.7.1.tgz',
	'cd132aea6f7055a49aa48ca0a61e7cd5');
download('BLAS','http://www.netlib.org/blas/blast-forum/cblas.tgz',
	'http://www.netlib.org/blas/blast-forum',
	'cblas.tgz',
	'1e8830f622d2112239a4a8a83b84209a');
download('OpenBLAS','http://github.com/xianyi/OpenBLAS/tarball/v0.2.12',
	'http://www.openblas.net/',
	'OpenBLAS.tar.gz',
	'dfc868e0c134855639f036d2723bf4be',
	'BAD_CERT');

# downloading the binary package is required for Windows because
# compiling requires big amounts of RAM (more than 4GB). This is not a
# big package so we download it in any situation just in case an
# offline Windows compile follows.

download('OpenBLAS-Win64','http://downloads.sourceforge.net/project/openblas/v0.2.14/OpenBLAS-v0.2.14-Win64-int64.zip',
	'http://www.openblas.net/',
	'OpenBLAS-v0.2.14-Win64-int64.zip',
	'9f2d41076857a514b921bf0bf03b5d39');
download('OpenBLAS-Win32','http://downloads.sourceforge.net/project/openblas/v0.2.14/OpenBLAS-v0.2.14-Win32.zip',
	'http://www.openblas.net/',
	'OpenBLAS-v0.2.14-Win32.zip',
	'eefdf170439620d78fabb3139b7aeb2f');

download('FFTW','http://www.fftw.org/fftw-3.3.2.tar.gz',
	'http://www.fftw.org',
	'fftw-3.3.2.tar.gz',
	'6977ee770ed68c85698c7168ffa6e178');
download('freeYams','http://www.ann.jussieu.fr/~frey/ftp/archives/freeyams.2012.02.05.tgz',
	'http://www.ann.jussieu.fr/~frey/software.html',
	'freeyams.2012.02.05.tgz',
	'b7c82a256a3e59beeb2b578de93a4e0b');
download('Gmm++','http://download.gna.org/getfem/stable/gmm-4.2.tar.gz',
	'http://download.gna.org/getfem/html/homepage/download.html',
	'gmm-4.2.tar.gz',
	'35fe900f7459c49f4b4337dc691c8cdf');
download('Hips','http://hips.gforge.inria.fr/release/hips-1.2b-rc4.tar.gz',
	'http://hips.gforge.inria.fr/',
	'hips-1.2b-rc4.tar.gz',
	'78720bf9bbbce5e174bdbdbaa1e5d7b4');
download('Ipopt','http://www.coin-or.org/download/source/Ipopt/Ipopt-3.12.4.tgz',
	'https://projects.coin-or.org/Ipopt',
	'Ipopt-3.12.4.tgz',
	'12a8ecaff8dd90025ddea6c65b49cb03');
download('METIS','http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz',
	'http://www.netlib.org/linalg/',
	'metis-5.1.0.tar.gz',
	'5465e67079419a69e0116de24fce58fe');
download('ParMETIS','http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/parmetis-4.0.3.tar.gz',
	'http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/',
	'ParMetis-4.0.3.tar.gz',
	'f69c479586bf6bb7aff6a9bc0c739628');
download('MMG3D','http://www.math.u-bordeaux1.fr/~dobrzyns/logiciels/download/mmg3d4.0.tgz',
	'http://www.math.u-bordeaux1.fr/~dobrzyns/logiciels/mmg3d.php',
	'mmg3d4.0.tgz',
	'bfc2b0373bc208e0512415d1aa2e76a1');
download('mshmet','http://www.ann.jussieu.fr/~frey/ftp/archives/mshmet.2012.04.25.tgz',
	'http://www.ann.jussieu.fr/~frey/software.html',
	'mshmet.2012.04.25.tgz',
	'427f397e0602efc56aa897d38a8e9bfa');
download('MUMPS','http://mumps.enseeiht.fr/MUMPS_5.0.2.tar.gz',
	'http://mumps.enseeiht.fr/',
	'MUMPS_5.0.2.tar.gz',
	'591bcb2c205dcb0283872608cdf04927');
download('NLopt','http://ab-initio.mit.edu/nlopt/nlopt-2.2.4.tar.gz',
	'http://ab-initio.mit.edu/wiki/index.php/NLopt',
	'nlopt-2.2.4.tar.gz',
	'9c60c6380a10c6d2a06895f0e8756d4f');
download('pARMS','http://www-users.cs.umn.edu/~saad/software/pARMS/pARMS_2.2.php',
	'http://www-users.cs.umn.edu/~saad/software/pARMS',
	'pARMS_2.2.tar.gz',
	'be0b4a539d78b9b2b7faf32ff83de822');
download('PaStiX','https://gforge.inria.fr/frs/download.php/21873/pastix_release_2200.tar.bz2',
	'https://gforge.inria.fr/projects/pastix/',
	'pastix_release_2200.tar.bz2',
	'c82b1808084f183dc8dfd07b1deef694',
	'BAD_CERT'); # web certificate from gforge.inria.fr is rejected
download('ScaLAPACK','http://www.netlib.org/scalapack/scalapack-2.0.2.tgz',
	'http://www.netlib.org/scalapack/',
	'scalapack-2.0.2.tgz',
	'2f75e600a2ba155ed9ce974a1c4b536f');
download('Scotch','https://gforge.inria.fr/frs/download.php/file/34618/scotch_6.0.4.tar.gz',
	'https://gforge.inria.fr/projects/scotch/',
	'scotch_6.0.4.tar.gz',
	'd58b825eb95e1db77efe8c6ff42d329f',
	'BAD_CERT'); # web certificate from gforge.inria.fr is rejected
download('SuiteSparse','http://faculty.cse.tamu.edu/davis/SuiteSparse/SuiteSparse-4.4.4.tar.gz',
	'http://faculty.cse.tamu.edu/davis/SuiteSparse/',
	'SuiteSparse-4.4.4.tar.gz',
	'e0af74476935c9ff6d971df8bb6b82fc') ;
download('SuperLU_DIST','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_dist_3.0.tar.gz',
	'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/',
	'superlu_dist_3.0.tar.gz',
	'1d77f10a265f5751d4e4b59317d778f8');
download('SuperLU','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_5.2.1.tar.gz',
	'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/',
	'superlu_5.2.1.tar.gz',
	'3a1a9bff20cb06b7d97c46d337504447');
download('TetGen','http://www.tetgen.org/1.5/src/tetgen1.5.1-beta1.tar.gz',
	'http://www.tetgen.org/1.5/src/',
	'tetgen1.5.1-beta1.tar.gz',
	'3d55c197bcbfc611b7ced6f343643756');
download('PETSc','http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-lite-3.9.2.tar.gz',
	'http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/',
	'petsc-lite-3.9.2.tar.gz',
	'647aa502b79f1fcedfbdf19a61d991f6');
download('SLEPc','http://slepc.upv.es/download/distrib/slepc-3.9.1.tar.gz',
	'https://bitbucket.org/slepc/slepc/get/',
	'slepc-3.9.1.tar.gz',
	'7eae35e7bcfe5c5144677731089d3ee9');
download('hpddm','https://github.com/hpddm/hpddm/archive/d2c1634c4367f0bd5260cb82cb6d94fcb112f189.zip',
	'https://github.com/hpddm',
	'hpddm.zip',
	'361505c1d96ff48a9e9af5055b548829');

# run all downloads concurrently

if($can_use_threads){
	my @threads;
	foreach(@downloads){push @threads,threads->create(\&downloadone,$_)}
	foreach(@threads){$_->join()}
}
else{
	foreach(@downloads){downloadone($_)}
}

if($errors ne ''){
	print "\n$errors";
	exit 1;
}

sub download{
	my($title,$url,$lic,$pkg,$md5,$opts)=@_;

	# skip packages that have not been requested explicitely
	return if($only && !defined $packs{$title});

	# skip packages that are already present
	if(-f "pkg/$pkg" && !$opts{f}){
		my $md5check=md5_hex(`cat pkg/$pkg`);
		if( ( $md5 eq "none") || ($md5check eq $md5)){
			print "$title $pkg done\n";
			return;
		}
		else {
			print "$title $pkg  md5 change => reget \n";
		}
	}

	# we do not store the answers to these questions. To repeat the same downloads without manual input, options "-a" and
	# "-o names" are provided.

	if(!$opts{a}){
		print "$title: please check the licence at $lic. Do you want to download $url? (yN)\n";
		my $ans=uc <STDIN>;
		chomp $ans;
		return if $ans ne 'Y';
	}

	# uses [[file:../build/download]]
	push @downloads,"$url,pkg/$pkg,$md5,$opts";
}

sub downloadone{
	my($url,$pkg,$md5,$opts)=split(/,/,$_[0]);
	my $cmd="../build/download $url $pkg $opts";
	print "$cmd\n";
	system $cmd;
	if($?){
		print "Download failed from $url\n";
		my $url="http://www.freefem.org/ff++/$pkg";
		my $cmd="../build/download $url $pkg $opts";
		print "Try other site: $url\n";
		system $cmd;
		if($?){
			print "Download failed from $url\n";
			my $url="http://104.46.50.187/$pkg";
			my $cmd="../build/download $url $pkg $opts";
			print "Try other site: $url\n";
			system $cmd;
			if ($?){
				$errors.="ERROR: $cmd FAILED\n"
			}
		}
	}
	# check if resulting package contents are valid
	my $md5check=md5_hex(`cat $pkg`);
	if( ( $md5 ne "none") && ($md5check ne $md5)){$errors.="ERROR: INVALID MD5 for $pkg  $md5check\n"}
}

# Backup
#download('METIS','http://www.netlib.org/linalg/metis-4.0.tar.gz','http://www.netlib.org/linalg/','metis-4.0.tar.gz',
#	 '0aa546419ff7ef50bd86ce1ec7f727c7');
#download('ParMETIS','http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/OLD/ParMetis-3.1.1.tar.gz',
#	 'http://glaros.dtc.umn.edu/gkhome/views/metis','ParMetis-3.1.1.tar.gz','57318dbaddff2c3d1ef820cff0bf87b0');
# http://glaros.dtc.umn.edu/gkhome/fetch/sw/parmetis/parmetis-4.0.3.tar.gz
#download('MUMPS','http://graal.ens-lyon.fr/MUMPS/MUMPS_4.10.0.tar.gz',
#	 'http://graal.ens-lyon.fr/MUMPS/','MUMPS_4.10.0.tar.gz','959e9981b606cd574f713b8422ef0d9f');
#download('MUMPS','http://graal.ens-lyon.fr/MUMPS/MUMPS_5.0.0.tar.gz',
#	 'http://graal.ens-lyon.fr/MUMPS/','MUMPS_5.0.0.tar.gz','3c6aeab847e9d775ca160194a9db2b75');
#download('MUMPS','http://graal.ens-lyon.fr/MUMPS/MUMPS_5.0.1.tar.gz',
#	 'http://graal.ens-lyon.fr/MUMPS/','MUMPS_5.0.1.tar.gz','b477573fdcc87babe861f62316833db0');
# ALH - 6/1/14 - web certificate for gforge.inria.fr is rejected
# ALH - 6/1/14 - web certificate for gforge.inria.fr is rejected
#https://gforge.inria.fr/frs/download.php/file/34099/scotch_6.0.3.tar.gz
#download('Scotch','https://gforge.inria.fr/frs/download.php/file/34099/scotch_6.0.3.tar.gz',
#	 'https://gforge.inria.fr/projects/scotch/','scotch_6.0.3.tar.gz','10b0cc0f184de2de99859eafaca83cfc',
#	 'BAD_CERT');
# download('SuiteSparse','http://www.cise.ufl.edu/research/sparse/SuiteSparse/SuiteSparse-4.3.1.tar.gz',
# 	 'http://www.cise.ufl.edu/research/sparse/SuiteSparse/','SuiteSparse-4.3.1.tar.gz',
# 	 'f8f26a3b1c7f82444c0db0b375215287');

# reput version 4.4.4 of umpfack pb of install under windows ... F. H.
#	 'http://faculty.cse.tamu.edu/davis/SuiteSparse/','SuiteSparse-4.5.5.tar.gz',
#	 '0a5b38af0016f009409a9606d2f1b555') ;
#download('SuperLU','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_4.3.tar.gz',
#	 'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/','superlu_4.3.tar.gz','b72c6309f25e9660133007b82621ba7c');
# PB SuperLU_DIST with version 5.2.1 -> return to verison 3.0
#  DO F. HECHT but no time
#download('SuperLU_DIST','http://crd-legacy.lbl.gov/~xiaoye/SuperLU/superlu_dist_5.2.1.tar.gz',
#	 'http://crd-legacy.lbl.gov/~xiaoye/SuperLU/','superlu_dist_5.2.1.tar.gz','af857778ffeb04aea02aa4843e6e8e1d');
# http://www.tetgen.org/1.5/src/tetgen1.5.1-beta1.tar.gz
#download('TetGen','http://wias-berlin.de/software/tetgen/files/tetgen1.4.3.tar.gz',
#	 'http://wias-berlin.de/software/tetgen/','tetgen1.4.3.tar.gz','d6a4bcdde2ac804f7ec66c29dcb63c18');
## got back to version 3.8 (for slepc and petc )
#download('PETSc','http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/petsc-lite-3.9.0.tar.gz',
#	 	 'http://ftp.mcs.anl.gov/pub/petsc/release-snapshots/','petsc-lite-3.9.0.tar.gz','6958049cafdbb7586c50e09b54e6fce9');
