# This file is part of Email-Reminder.
#
# Email-Reminder 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.
#
# Email-Reminder 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 Email-Reminder; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301, USA.

package EmailReminder::Event;

# Base class for all other events.
#
# This class should never be used directly, use a derived class instead.

use strict;
use warnings;

use Date::Manip;
use XML::DOM;

use EmailReminder::Utils;

# XML tags
__PACKAGE__->mk_accessors(qw(name));

sub mk_accessors {
    my ($self, @field_names) = @_;

    # get the classname since it might be a derived class calling this
    my $class = ref $self || $self;

    foreach my $field_name ( @field_names ) {
        my $get_method = sub {
            my ($self) = @_;
            my $valid_sub = "valid_$field_name";
            my $value = EmailReminder::Utils::get_node_value($self->{XML_NODE}, $field_name);
            return $self->$valid_sub( $value );
        };

        my $set_method = sub {
            my ($self, $new_value) = @_;
            return EmailReminder::Utils::set_node_value($self->{XML_NODE}, $field_name, $new_value);
        };

        {
            no strict 'refs';
            *{"${class}::get_$field_name"} = $get_method;
            *{"${class}::set_$field_name"} = $set_method;
        }
    }
    return 1;
}

# other XML tags, attributes and values
my $REMINDER_TAG = 'reminder';
my $REMINDERS_TAG = 'reminders';
my $RECIPIENT_TAG = 'recipient';
my $RECIPIENTS_TAG = 'recipients';

my $EMAIL_ATTR = 'email';
my $NAME_ATTR = 'name';
my $TYPE_ATTR = 'type';

my $DAYS_BEFORE_VAL = 'days before';
my $SAME_DAY_VAL = 'same day';

# Hard-coded value for this event's type (class method)
sub get_type
{
    return;
}

# Number of fields this event adds to its parent (class method)
sub get_nb_fields
{
    return 1;
}

sub valid_name {
    my ($class, $new_value) = @_;
    return $new_value;
}

sub new
{
    my $class = shift;
    my $event_node = shift;
    my $id = shift;

    my $self = { "OCCURRING" => 0,
                 "XML_NODE" => $event_node,
                 "ID" => $id,
                 "DATA" => [$id],
            };
    
    bless $self, $class;

    # Create empty data array
    my $count = $self->get_nb_fields() - 1;
    for (my $i = 0; $i < $count; $i++) {
        push(@{$self->{DATA}}, undef);
    }

    # Where to send this reminder email
    my $recipients = $self->{XML_NODE}->getElementsByTagName($RECIPIENTS_TAG)->item(0);
    if (defined($recipients)) {
        $self->{RECIPIENTS_NODE} = $recipients;
        $self->{RECIPIENTS_CACHE} = $self->get_recipients();
    }

    # Process reminders
    my $reminders = $self->{XML_NODE}->getElementsByTagName($REMINDERS_TAG)->item(0);
    if (defined($reminders)) {
        $self->{REMINDERS_NODE} = $reminders;
        $self->{REMINDERS_CACHE} = $self->get_reminders();
    }

    return $self;
}

sub get_recipients
{
    my $self = shift;

    if (!defined($self->{RECIPIENTS_CACHE})) {
        my @recipients = ();

        if (defined($self->{RECIPIENTS_NODE})) {
            foreach my $recipient ($self->{RECIPIENTS_NODE}->getElementsByTagName($RECIPIENT_TAG)) {
                my $email = $recipient->getAttribute($EMAIL_ATTR);
                if (defined($email)) {
                    my $fname = undef;
                    my $lname = undef;
                    my $fullname = $recipient->getAttribute($NAME_ATTR);

                    my @name_parts = split(/ /, $fullname);
                    $fname = $name_parts[0];
                    $lname = $name_parts[-1] if @name_parts > 1;

                    push(@recipients, [$email, $fname, $lname]);
                }
            }
        }
        
        $self->{RECIPIENTS_CACHE} = \@recipients;
    }
    return $self->{RECIPIENTS_CACHE};
}

sub get_reminders
{
    my $self = shift;

    if (!defined($self->{REMINDERS_CACHE})) {
        my @reminders = ();

        if (defined($self->{REMINDERS_NODE}))
        {
            foreach my $reminder ($self->{REMINDERS_NODE}->getElementsByTagName($REMINDER_TAG)){
                my $type = $reminder->getAttribute($TYPE_ATTR);
                
                if ($type eq $SAME_DAY_VAL) {
                    push(@reminders, 0);
                    
                    if ($self->will_occur("")) {
                        $self->{WHEN} = "today";
                        $self->{OCCURRING}++;
                    }
                }
                elsif (($type eq $DAYS_BEFORE_VAL) && 
                       ($reminder->getFirstChild()))
                {
                    my $days = $reminder->getFirstChild()->getNodeValue();
                    push(@reminders, $days);
                    
                    if ($self->will_occur($days)) {
                        if ($days > 1) {
                            my $upcoming_date = DateCalc("today", "+${days}days");
                            $self->{WHEN} = "in $days days (" . UnixDate($upcoming_date, "%A %b %e") . ")";
                        }
                        elsif ($days == 1) {
                            $self->{WHEN} = "tomorrow";
                        }
                        elsif ($days == 0) {
                            $self->{WHEN} = "today";
                        }
                        else { 
                            next; # Negative days are ignored
                        } 
                        
                        $self->{OCCURRING}++;
                    }
                }
            }
        }

        $self->{REMINDERS_CACHE} = \@reminders;
    }

    return $self->{REMINDERS_CACHE};
}

sub is_occurring
{
    my $self = shift;
    return $self->{OCCURRING};
}

sub get_message
{
    my $self = shift;

    # destination user
    my $first_name = shift || 'there';

    my $body = $self->get_message_body(@_);

    my $message = "";
    $message = <<"MESSAGEEND" if $body;
Hi $first_name,

$body
Have a good day!

--
Sent by Email-Reminder $EmailReminder::Utils::VERSION
https://launchpad.net/email-reminder
MESSAGEEND

    return $message;
}

sub data
{
    my $self = shift;
    return $self->{DATA};
}

sub get_id
{
    my $self = shift;
    return $self->{ID};
}

1;
