package PMG::RuleDB::TimeFrame;

use strict;
use warnings;
use DBI;
use Digest::SHA;

use PMG::Utils;
use PMG::RuleDB::Object;

use base qw(PMG::RuleDB::Object);

sub otype {
    return 2000;
}

sub oclass {
    return 'when';
}

sub otype_text {
    return 'TimeFrame';
}

my $hm_to_minutes = sub {
    my ($hm) = @_;

    if ($hm =~ m/^(\d+):(\d+)$/) {
        my @tmp = split(/:/, $hm);
	return $tmp[0]*60+$tmp[1];
    }
    return 0;
};

my $minutes_to_hm = sub {
    my ($minutes) = @_;

    my $hour = int($minutes/60);
    my $rest = int($minutes%60);

    return sprintf("%02d:%02d", $hour, $rest);
};

sub new {
    my ($type, $start, $end, $ogroup) = @_;

    my $class = ref($type) || $type;

    my $self = $class->SUPER::new($class->otype(), $ogroup);

    $start //= "00:00";
    $end //= "24:00";

    # Note: allow H:i or integer format
    if ($start =~ m/:/) {
	$start = $hm_to_minutes->($start);
    }
    if ($end =~ m/:/) {
	$end = $hm_to_minutes->($end);
    }

    $self->{start} = $start;
    $self->{end} = $end;

    return $self;
}

sub load_attr {
    my ($type, $ruledb, $id, $ogroup, $value) = @_;

    my $class = ref($type) || $type;

    defined($value) || return undef;

    my ($sh, $sm, $eh, $em) = $value =~ m/(\d+):(\d+)-(\d+):(\d+)/;

    my $start = $sh*60+$sm;
    my $end = $eh*60+$em;

    my $obj = $class->new($start, $end, $ogroup);
    $obj->{id} = $id;

    $obj->{digest} = Digest::SHA::sha1_hex ($id, $start, $end, $ogroup);

    return $obj;
}

sub save {
    my ($self, $ruledb) = @_;

    defined($self->{ogroup}) || return undef;
    defined($self->{start}) || return undef;
    defined($self->{end}) || return undef;

    my $start = $minutes_to_hm->($self->{start});
    my $end = $minutes_to_hm->($self->{end});

    my $v = "$start-$end";

    if (defined ($self->{id})) {
	# update

	$ruledb->{dbh}->do(
	    "UPDATE Object SET Value = ? WHERE ID = ?", undef, $v, $self->{id});

    } else {
	# insert

	my $sth = $ruledb->{dbh}->prepare(
	    "INSERT INTO Object " .
	    "(Objectgroup_ID, ObjectType, Value) " .
	    "VALUES (?, ?, ?);");

	$sth->execute($self->ogroup, $self->otype, $v);

	$self->{id} = PMG::Utils::lastid($ruledb->{dbh}, 'object_id_seq');
    }

    return $self->{id};
}

sub when_match {
    my ($self, $t) = @_;

    my ($sec,$min,$hour) = localtime($t);

    my $amin = $hour*60 + $min;

    if ($self->{end} >= $self->{start}) {

	return $amin >= $self->{start} && $amin <= $self->{end};

    } else {

	return  ($amin <= $self->{end}) || ($amin >= $self->{start});
    }
}

sub short_desc {
    my $self = shift;

    my $start = $minutes_to_hm->($self->{start});
    my $end = $minutes_to_hm->($self->{end});

    return "$start-$end";
}

sub properties {
    my ($class) = @_;

    return {
	start => {
	    description => "Start time in `H:i` format (00:00).",
	    type => 'string',
	    pattern => '\d?\d:\d?\d',
	},
	end => {
	    description => "End time in `H:i` format (00:00).",
	    type => 'string',
	    pattern => '\d?\d:\d?\d',
	},
    };
}

sub get {
    my ($self) = @_;

    return {
	start => $minutes_to_hm->($self->{start}),
	end => $minutes_to_hm->($self->{end}),
    };
}

sub update {
    my ($self, $param) = @_;

    $self->{start} = $hm_to_minutes->($param->{start});
    $self->{end} = $hm_to_minutes->($param->{end});
}


1;

__END__

=head1 PMG::RuleDB::TimeFrame

A WHEN object to check for a specific daytime.

=head2 Attribues

=head3 start

Start time im minutes since 00:00.

=head3 end

End time im minutes since 00:00.

=head2 Examples

    $obj = PMG::RuleDB::TimeFrame->new(8*60+15, 16*60+30);

Represent: 8:15 to 16:30

Note: End time is allowed to be smaller that start time.
