package HNS::Collection;
# $Id: Collection.pm,v 1.16 2000/05/16 17:20:49 masato Exp $
###############################################################

=head1 NAME

HNS::Collection   :  diary collection class

=head1 SYNOPSIS

  use HNS::Collection;

  my $col = new HNS::Collection;
  $col->Read($y);
  $col->Print($y, $m, $d);
  #$col->PrintRecent;   # recent

=cut

################################################################
use strict;
use ObjectTemplate;
@HNS::Collection::ISA = qw(ObjectTemplate);

use HNS;
use HNS::Diary;
use DateTime::Date;

#

=head1 MEMBER VARIABLES

 diarys         日記群
 last_modified  最終更新時刻
 mode           モード
 start_time     開始時刻
 end_time       終了時刻
 year,month,day 年月日

=cut

attributes qw(diarys last_modified mode start_time end_time year month day);
use vars qw(%FootMessages);


=head1 STATIC VARIABLES

 %FootMessage  フットメッセージ

=cut

%FootMessages = 
    ('HasContent'=>"Diary for %num day(s)\n",
     'NoContent' =>"No Match\n");

################################################################
sub initialize($)
{
    my $self = shift;
    $self->diarys({});
}
################################################################

=head2 $c->Read($year, $month, $day);

$year, $month, $day の日記を読み込む。
$day は日付指定のほかに、一桁目指定、旬指定(a,b,c)ができる。

=cut

sub Read($$$$)
{
    my ($self, $year, $month, $day) = @_;

    # set date
    $self->year($year), $self->month($month), $self->day($day);
    # start time
    $self->start_time(time);

    $day = '(0\d|10)' if $day eq "a";
    $day = '(11|12|13|14|15|16|17|18|19|20)' if $day eq "b";
    $day = '(21|22|23|24|25|26|27|28|29|30|31)' if $day eq "c";

    $self->collect_yearly($year);
    for my $ymd (sort keys %{$self->diarys}){
	my $diary = $self->diarys->{$ymd};
	$diary->filename =~ /d(\d+)\.hnf/;
	next unless ($1 =~ /$year$month$day/);
	$diary->Read;
    }
}


=head2 $c->ReadDay($month, $day);

$month, $day の日記を読み込む。

=cut

sub ReadDay($$$)
{
    my ($self, $month, $day) = @_;

    # set date
    $self->month($month), $self->day($day);
    # start time
    $self->start_time(time);
    $self->mode('RECENT');

    my $DiaryDir = $HNS::System::DiaryDir;
    my (@files, @years);

    opendir DIR, $DiaryDir;
    @files = grep /^d\d{4,}$month$day\.hnf$/, readdir DIR;
    closedir DIR;

    foreach my $file (@files) {
        my $diary = new HNS::Diary(filename=>"$DiaryDir/$file");
        $file =~ /^d(.*)\.hnf$/;
        $self->diarys->{$1} = $diary;
    }

    opendir DIR, $DiaryDir;
    @years = grep /^(\d{4,})$/, readdir DIR;
    closedir DIR;
    foreach my $year (@years) {
        my $ymd = $year . $month . $day;
        if ((-f "$DiaryDir/$year/d$ymd.hnf") && 
	(!$self->diarys->{$ymd})) { 
            my $diary = new HNS::Diary(filename=>
		"$DiaryDir/$year/d$ymd.hnf"); 
	    $self->diarys->{$ymd} = $diary;
	}
    } 

    # read cache file for only cache mode
    if (($HNS::System::Caching) && ($HNS::System::AllowCacheOnly)) {
        my $CacheDir = $HNS::System::CacheDir;
        opendir DIR, $CacheDir;
        @years = grep /^(\d{4,})$/, readdir DIR;
        closedir DIR;
        foreach my $year (@years) {
            my $ymd = $year . $month . $day;
            if ((-f "$DiaryDir/$year/d$ymd.hnf") &&
            (!$self->diarys->{$ymd})) {
                my $diary = new HNS::Diary(filename=>
                  "$DiaryDir/$year/d$ymd.hnf");
                $self->diarys->{$ymd} = $diary;
            }
        }
    }

    for my $ymd (reverse sort keys %{$self->diarys}){
        my $diary = $self->diarys->{$ymd};
        $diary->Read;
        # set date
        unless ($self->year){
            $self->year($diary->year);
            $self->month($diary->month);
            $self->day($diary->day);
        }
    }

    # set now date if no diary
    unless ($self->year){
        $self->year(sprintf("%04d", $HNS::Status->start_time->year));
        $self->month(sprintf("%02d", $HNS::Status->start_time->month));
        $self->day(sprintf("%02d", $HNS::Status->start_time->day));
    }
}


=head2 $c->ReadRecent($max);

最新 $max 分を読み込む。

=cut

sub ReadRecent($;$)
{
    my ($self, $max) = @_;
#    $max ||= 5;
    
    $self->start_time(time);
    $self->mode('RECENT');
    my $year = $HNS::Status->start_time->year;

    my $cnt = 0;
    my $y_cnt;
    # read this year and last year, for acrossing year
    # for exapmle: 1999/01/02, 1999/01/01, 1998/12/31, 1998/12/30...
#print "content-type: text/html\n\n";
    while ($cnt<$max){
	# read file info : first this year, second last year
	$self->collect_yearly($year);
	for my $ymd (reverse sort keys %{$self->diarys}){
#print "$cnt $ymd ";
	    my $diary = $self->diarys->{$ymd};
#print "$diary->year $year ";
	    next unless $diary->year == $year;
	    last if (++$cnt>$max);	# read done
#print "read<br>";
	    $diary->Read;
	    # set date
	    unless ($self->year){
		$self->year($diary->year);
		$self->month($diary->month);
		$self->day($diary->day);
	    }
	    # last modified
	    if ($diary->last_modified > $self->last_modified){
		$self->last_modified($diary->last_modified);
	    }
	}
	last if ++$y_cnt>1;  # read done of this year and last year
	$year--;
    }
    # set now date if no diary
    unless ($self->year){
	$self->year(sprintf("%04d", $HNS::Status->start_time->year));
	$self->month(sprintf("%02d", $HNS::Status->start_time->month));
	$self->day(sprintf("%02d", $HNS::Status->start_time->day));
    }
}
# return year-matched file list (directory containted)
# private:
sub collect_yearly ($$)
{
    my ($self, $year) = @_;
    
    for my $dir ($HNS::System::DiaryDir, "$HNS::System::DiaryDir/$year"){
	opendir(DIR, $dir) || next;
#	for my $file (sort readdir(DIR)){
	my $file;
	while ($file = readdir(DIR)){
	    next unless (-f "$dir/$file" &&	# normal file
			 $file =~ /^d($year\d{4})\.hnf$/ &&
			 !$self->diarys->{$1});
	    my $diary = new HNS::Diary(filename=>"$dir/$file");
	    $self->diarys->{$1} = $diary;
	}
    }

    # read cache file for only cache mode
    if (($HNS::System::Caching) && ($HNS::System::AllowCacheOnly)) {
        my $dir = "$HNS::System::CacheDir/$year";
        opendir(DIR, $dir);
        my $file;
        while ($file = readdir(DIR)){
            next unless (-f "$dir/$file" &&	# normal file
                         $file =~ /^($year\d{4})\.xhnf$/ &&
                         !$self->diarys->{$1});
            my $diary = new HNS::Diary(filename=>
			"$HNS::System::DiaryDir/$year/d$1.hnf");
            $self->diarys->{$1} = $diary;
        }
    }

    return;
}
################################################################

=head2 $c->Print;

表示する

=cut

sub Print($)
{
    my $self = shift;

    my @ymds = sort keys %{$self->diarys};
    @ymds = reverse @ymds if $HNS::System::AlwaysReverse eq "ON" || 
				$self->mode eq 'RECENT';

    my $num;
    for (@ymds){
	my ($md, $diary) = ($_, $self->diarys->{$_});
#	print "md:$md, ";
	next unless $diary->read_done;
	my $reverse_sec;
	if (($self->mode eq 'RECENT') && ($HNS::System::NewReverse)) {
	    $reverse_sec = 1;
	}
	$diary->Print($reverse_sec);
	$num++;
    }
    # Footer
    my $msg = ($num) ? $FootMessages{'HasContent'} :
	$FootMessages{'NoContent'};
    $msg =~ s/%num/$num/g;
    print $msg;
    $self->end_time(time);
}
################################################################
1;
