package MailScanner::IMAP;

use MailScanner;
use base MailScanner;

use strict;
use warnings;

use Mail::IMAPClient::AutoConfigured;

use Class::Std::Utils;
{
	my %imap_of;
	my %should_expunge_of;
	
	sub new
	{
		my ( $class ) = @_;

        my $new_object = bless \do{ my $anon_scalar }, $class;
                
		$imap_of{ ident $new_object } = Mail::IMAPClient::AutoConfigured->new( 
			Uid 			 => 1,
			IgnoreSizeErrors => 1 # Gmail's IMAP implementation doesn't return correct sizes
		);
		$should_expunge_of{ ident $new_object } = 0;

        return $new_object;
	}
	
	sub DESTROY
	{
		my $self = shift @_;
		
		delete $imap_of{ ident $self };
		delete $should_expunge_of{ ident $self };
	}
	
	sub connect
	{
		my ( $self, $hostname, $port, $ssl, $user, $password, $error_ref ) = @_;
		my $imap = $self->imap_();
		
		$imap->Server( $hostname );
		$imap->Port( $port );
		$imap->User( $user );
		$imap->Password( $password );
		
		if ( !$imap->connect( Ssl => $ssl ) ) {
			$$error_ref = $@;
			return 0;
		}
		
		if ( !$imap->select( "INBOX" ) ) {
			$$error_ref = $@;
			return 0;
		}
		
		$imap->Peek( 1 );
		
		return 1;
	}
	
	sub disconnect
	{
		my ( $self ) = @_;
		
		$self->imap_()->expunge() if $should_expunge_of{ ident $self };
		$self->imap_()->disconnect();
	}

	sub getCandidateMessageNumbers
	{
		my ( $self, $config, $message_number_to_uid_ref, $error_ref ) = @_;
		my @message_nums;
		
		if ( $config->{ LastMessageTime } ) {
			@message_nums = $self->imap_()->since( $config->{ LastMessageTime } );
		}
		else {
			@message_nums = $self->imap_()->since( time() - ( $config->{ MaxLookbackDays } * 24 * 60 * 60 ) );
		}

		@message_nums = () if !@message_nums || !defined( $message_nums[0] );
		
		$$error_ref = $@ if $@;
		
		return @message_nums;
	}
	
	sub getMessageHeaders
	{
		my ( $self, $message_number, $req_headers_ref, $error_ref ) = @_;
		
		my $headers_ref = $self->imap_()->parse_headers( $message_number, @$req_headers_ref );
		
		$$error_ref = $@ if $@;
		
		return $headers_ref;
	}
	
	sub getRawMessage
	{
		my ( $self, $message_number, $error_ref ) = @_;
		
		my $string = $self->imap_()->message_string( $message_number );
		
		$$error_ref = $@ if $@;
		
		return $string;
	}

	sub deleteMessage
	{
		my ( $self, $message_number ) = @_;
		
		$should_expunge_of{ ident $self } = 1;
		
		$self->imap_()->delete_message( $message_number );
	}
	
	sub imap_
	{
		return $imap_of{ ident shift @_ };
	}
}

1;
