package Massmailer::Scan;

use strict;
use warnings;

our $SKIP_MAIL_DOMAIN = [] unless defined $SKIP_MAIL_DOMAIN;
our $warnings = 1 unless defined $warnings;
our $cli;
our $dbh;

my $DOMAIN_PLAN = {};
my $good_email_fname = '';


END {
	$good_email_fname && unlink $good_email_fname;# || die "Can't unlink $good_email_fname" );
}


sub scan_emails
{
	$good_email_fname = _generate_tmp_fname();
	unlink $good_email_fname;

	my %skip_domains = map {$_ => 1} @$SKIP_MAIL_DOMAIN;

	#my $i = 0;

	## help CGP to scan domains in alphabet order
	foreach my $domain (sort {$a cmp $b} keys %$DOMAIN_PLAN) {

		#print '.'
		#	unless $i++ % 100;

		#print "$domain";

		## domain in skip list, add all emails without checking
		if( exists $skip_domains{$domain} ) {
			#print "| skipped..\n";
			write_good_emails($domain);
			## write all emails to good email file
			next;
		}

		## domain is hosted on dir.bg, if yes, add emails
		if( check_dir_hosted_domain($domain) ) {
			## all valid email written
			next;
		};

		## check alias mail.*
		## domain is hosted on dir.bg, if yes, add emails
		if( check_dir_hosted_domain('mail.'.$domain) ) {
			## all valid email written
			next;
		};

		## domain not found add all emails
		write_good_emails($domain);
		#print "\n";
	}

	#print "\n";

	return undef;
}


sub check_dir_hosted_domain
{
	my $domain = shift or die "No domain given!";

	my $AccountList = $cli->ListAccounts($domain);

	unless( $cli->isSuccess ) {
		die "FATAL: ".$cli->getErrMessage
			unless $cli->getErrMessage =~ /unknown secondary domain name/;

		return undef;
	}

	if( scalar(keys %$AccountList) ) {
#		print "\nLISTACCOUNTS $domain (".scalar(keys %$AccountList)."):\n";
		## check all email
		## write all emails to good email file
		write_good_emails($domain, [keys %$AccountList]);
	}

	return 1;
}


sub write_good_emails
{
	my $domain = shift or die "No domain given!";
	my $EXIST_EMAILS = shift;

	my %orig_emails = map {$_ => 1} @{$DOMAIN_PLAN->{$domain}};

	open(F, ">>$good_email_fname") or die "Can't open $good_email_fname: $!";

	my @towrite = ();
	if( $EXIST_EMAILS ) {
		my %real_emails = map {$_ => 1} @$EXIST_EMAILS;

		foreach my $email (keys %orig_emails) {
			push @towrite, $email.'@'.$domain
				if exists $real_emails{$email};
		}
		#print scalar @towrite." - $domain;\n";
	}
	else {
		push @towrite, $_.'@'.$domain
			foreach (keys %orig_emails);
	}

	print F join("\n", @towrite)."\n"
		if scalar @towrite;

	close F;

	return undef;
}


sub load_emails_list_from_file
{
	my $fname = shift or die "No fname given!";

	open(F, $fname) or die "Can't open $fname: $!";

	while(<F>) {

		my $email = _prepare_email( $_ );
		next
			unless $email;

		my ($account,$domain) = split /@/, lc($email), 2;

		push @{$DOMAIN_PLAN->{$domain}}, $account;
	}

	close F;

	$warnings && print scalar(keys %$DOMAIN_PLAN)." email domains loaded\n";

	return undef;
}


sub load_emails_list_from_db
{
	my $sql = shift or die "No sql given!";

	my $sth = $dbh->prepare($sql) or die $dbh->errstr;
	$sth->execute() or die $sth->errstr;

	while( my $row = $sth->fetchrow_arrayref() ) {

		my $email = _prepare_email( $row->[0] );
		next
			unless $email;

		my ($account,$domain) = split /@/, lc($email), 2;

		push @{$DOMAIN_PLAN->{$domain}}, $account;
	}

	$sth->finish();

	return undef;
}


sub _prepare_email
{
	my $str = shift;

	chomp $str;

	my $str_orig = $str;

	return undef
		unless $str;

	chop $str
		while( $str =~ /[\.,;]+$/ );

	if( index($str,'@')==-1 ) {
		$warnings && warn "Illegal mailbox $str!\n";
		return undef;
	}

	if( (my $pos = index($str,'?'))!=-1 ) {
		$str = substr($str, 0, $pos);
	}

	$str =~ tr/,/./;
	$str =~ s/ +//g;

	if( $str !~ /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9]+[a-zA-Z0-9.-]*[a-zA-Z0-9]+\.[a-zA-Z]{2,6}$/ ) {
		$warnings && warn "Not valid '$str' - '$str_orig'\n";
		return undef;
	}

	return $str;
}


sub _generate_tmp_fname
{
	return "/tmp/massmailer$$.".(localtime)[0];
}


sub save_to_file
{
	my $fname = shift or die "No filename given!";

	`mv $good_email_fname $fname`;
}


sub save_to_arrayref
{
	open(F, $good_email_fname) or die "Can't open '$good_email_fname'!";
	my @LIST = grep {chomp($_)} <F>;
	close F;

	unlink $good_email_fname;

	return \@LIST;
}

1;
