package Memories;
use strict;
our $VERSION = "1.2";
use Maypole::Application qw(Upload Authentication::UserSessionCookie -Debug);
use HTML::TagCloud;
use URI;
use Memories::Config;
use Memories::DBI;
use Memories::Photo;
use Memories::Comment;
use Memories::Tag;
use Memories::SystemTag;
use Memories::User;
use Memories::Album;
use URI::Escape;
use Calendar::Simple;
use XML::RSS;

Memories->config->auth->{ user_field } = "name";
Memories->config->model("Maypole::Model::CDBI::Plain");
Memories->setup([qw/ Memories::Photo Memories::User Memories::Tag
Memories::Album Memories::SystemTag/]);

sub message {
    my ($self, $message) = @_;
    push @{$self->{template_args}{messages}}, $message;
}

sub check_credentials {
    my $r = shift;
    my ($uid, $user) = $r->SUPER::check_credentials;
    #if (!$uid) { return (-1, undef) }
    return ($uid, $user);
}

sub do_rss {
    my $r = shift;
    $r->model_class->process($r);
    my $photos = $r->get_photos;
    my $rss = XML::RSS->new(version => "2.0");
    $rss->channel(
        title => ($r->config->{application_name}. " : ".ucfirst($r->action)." ".ucfirst($r->table)." ".($r->objects||[])->[0]) ,
        link  => $r->config->{uri_base}."/".$r->path
    );
    for my $item (@$photos) { 
        my $link = $r->config->{uri_base}."photo/view/".$item->id;
        $rss->add_item( title => $item->title, link => $link,
            description => 
    "<a href=\"$link\">
    <img src=\"". $item->thumb_url."\" alt=\"".$item->title."\"></a>",
            dc => { subject => join " ", $item->tags },
            pubDate => $item->uploaded->strftime("%a, %d %b %Y %H:%M:%S %z")
        )
    }
    $r->output($rss->as_string);
    $r->content_type("application/rss+xml");
    return
}

sub get_photos {
    my $r = shift;
    my $maybe_photos = $r->{objects}||[];
    return (@$maybe_photos && $maybe_photos->[0]->isa("Memories::Photo")) 
            ? $maybe_photos :
            ($r->{template_args}->{photos} || []);
}

sub last_search {
    my $r = shift;
    my $photos = $r->get_photos; 
    $r->{session}{last_search} = join ",", map { $_->id } @$photos 
        if @$photos > 1;
}

sub additional_data { 
    my $r = shift;
    if ($r->params->{view_cal}) { 
    $r->{template_args}{view_cal} = eval {
            Time::Piece->strptime($r->{params}{view_cal}, "%Y-%m-%d") }; 
    }
    $r->{template_args}{now} = Time::Piece->new;
    if ($r->session) {
        (tied %{$r->session})->{lock_manager}->clean('/var/lib/memories/sessionlock', 3600) #remove files older than 1 hour
    }
    return $r->do_rss if ($r->params->{format} =~ /rss/)
}

use Maypole::Constants;
sub authenticate {
   my ($self, $r) = @_;
   return DECLINED if $self->path =~/static|store/; # XXX
   $r->get_user;
   return OK; 
}


use Cache::SharedMemoryCache;
my %cache_options = ( 'namespace' => 'MemoriesStuff',
                   'default_expires_in' => 600 );
my $cache =
   new Cache::SharedMemoryCache( \%cache_options ) or
     croak( "Couldn't instantiate SharedMemoryCache" );

sub zap_cache { $cache->Clear }
use Storable qw(freeze); use MIME::Base64;
sub do_cached {
    my ($self, $codeblock,$arg) = @_;
    my $key = 0+$codeblock; if ($arg) { $key .=":".encode_base64(freeze(\$arg));  }
    my $c = $cache->get(0+$codeblock); return @$c if $c;
    my @stuff = $codeblock->($arg);
    $cache->set(0+$codeblock, [ @stuff ]);
    return @stuff;
}

sub _recent_uploads { Memories::Photo->search_recent() }
sub _random { Memories::Photo->search_random() }

sub recent_uploads { shift->do_cached(\&_recent_uploads) }
sub random { shift->do_cached(\&_random) }
sub tagcloud { shift->do_cached(\&_tagcloud) }

sub _tagcloud {
    my $cloud = HTML::TagCloud->new();
    my $base = Memories->config->uri_base."tag/view/";
    for my $tagging (Memories::Tagging->search_summary) {
        my $name = $tagging->tag->name;
        $cloud->add($name,
            $base.uri_escape($name),
            $tagging->{count}
        )
    }
    $cloud
}

sub calendar {
    # shift->do_cached(\&_calendar, shift ) }
#sub _calendar {
    my $self = shift;
    my $arg = shift;
    my ($y, $m) = split /-/, ($arg || Time::Piece->new->ymd);
    my @m = Calendar::Simple::calendar($m, $y);
    my @month;
    foreach my $week (@m) {
        my @weekdays;
        foreach my $day (@$week) {
                my $d = { day => $day };
                if ($day) {
                    my $tag = "date:$y-$m-".sprintf("%02d", $day);
                    my ($x) = Memories::SystemTag->search(name => $tag);
                    if ($x) { $d->{tag} = "/system_tag/view/$tag" }
                }
                push(@weekdays, $d);
        }
        push(@month, \@weekdays);
    }
    return \@month;
}

# THIS IS A HACK

use Time::Seconds;
sub Time::Piece::next_month {
    my $tp = shift;
    my $month = $tp + ONE_MONTH;
    return if $month > Time::Piece->new;
    return $month
}
sub Time::Piece::prev_month {
    my $tp = shift;
    my $month = $tp - ONE_MONTH;
    return $month
}


sub tag_select {
    my ($r, $tags) = @_;
    my %counter;
    my @photos = Memories::Photo->sth_to_objects(Memories::Tag->multi_search(@$tags));
    for (map {$_->tags} @photos) { 
        $counter{$_->name}++; 
    } 
    delete $counter{$_->name} for @$tags;
    my @super;

    my $cloud = HTML::TagCloud->new();
    my $base = $r->config->uri_base.$r->path."/";
    my $tags;
    for my $name (sort {$a cmp $b} keys %counter) {
        if ($counter{$name} == @photos) {
            push @super, $name;
        } else {
            $cloud->add($name, $base.uri_escape($name), $counter{$name});
            $tags++;
        }
    }
    my %res;
    if (@super) { $res{super} = \@super }
    if ($tags) { $res{cloud} = $cloud }
    \%res;
}
1;
