package Vee::Controller::Forum::Create;

use strict;
use warnings;
use base 'Catalyst::Controller';
use Vee::BBCode;
use Vee::Utils;
use Vee::Utils::Forum;

use DateTime;

=head1 NAME

Vee::Controller::Forum::Create - Forum posting Controller

=head1 SYNOPSIS

See L<Vee>

=head1 DESCRIPTION

Catalyst Controller for creating new posts or threads.

=head1 METHODS

=cut

=head2 auto

=cut

sub auto : Private {
    my ($self, $c) = @_;
    
    if (!$c->user) {
        $c->vee_abort('You must be logged in to post.');
    } elsif ($c->req->method ne 'POST') {
        $c->vee_abort('This page should only be called as a <code>POST</code>.');
    }
    
    return 1;
}

=head2 post

=cut

sub post : Local : Args(0) {
    my ($self, $c) = @_;

    # TODO: make these redir to an actual post page when one exists
    $c->vee_abort('Please enter a message.') unless $c->req->params->{content} =~ /\S/;
    $c->vee_abort('No thread id specified.  This should not happen.  Sorry?') unless $c->req->params->{id};

    my $thread = $c->model('DBIC::Threads')->find( $c->req->params->{id}, { prefetch => 'forum' } )
        or $c->vee_abort('There is no thread with an id of ', $c->req->params->{id}, '.  It may have been nuked while you were typing your reply.');

    if (!can_post($c, $thread)) {
        $c->vee_abort('You do not have permission to reply to this thread.');
    }

    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
    if (@bbcode_errors) {
        $c->vee_abort("Your post contains invalid bbcode.  Please go back and fix it.");
    }
    $parsed_message = Vee::Utils::fix_newlines( $parsed_message );

    if ('preview' eq lc $c->req->params->{submit}) {
        $c->detach('post_preview', [ $thread ]);
    }

    # check for daabaru-post
    # TODO: apply this to thread creation too?  not as common..  and merge as well?
    my $last_post = $c->model('DBIC::Posts')->search({
        thread_id => $thread->id,
        time      => { '>=', time - $c->site_opts->{post_automerge_time} },
    }, {
        order_by  => 'time DESC',
    })->single;

    my $post;
    # only do merging/prevention if the last post is this user's	
    if ($last_post and $last_post->user_id == $c->user->obj->id and $last_post->flags !~ /deleted/) {
        if ($last_post->content eq $parsed_message) {
            $c->vee_abort("You have already posted that message recently.");
        }

        # TODO: what about formats/options of both posts?  not a problem now, but later.. 
		# XXX LATIEDIT: The only flag, afaik, is "deleted", which is considered above. Formats, I have no idea ...
        $post = $c->model('DBIC')->schema->txn_do( sub {
            my $edit = $c->model('DBIC::Edits')->create({
                post_id     => $last_post->id,
                user_id     => $c->user->obj->id,
                time        => time,
                old_content => $last_post->content,
            });
            $last_post->content(
                $last_post->content .
                "\n[hr][i]Automerged:[/i]\n" .
                $parsed_message
            );
            $last_post->last_edit_id( $edit->id );
            $last_post->time( time );
            $last_post->update;

            $thread->last_post_id( $last_post->id );
            $thread->last_post_time( time );
            $thread->update;

            return $last_post;
        } );
    } else {
        # create the post
        $post = $c->model('DBIC')->schema->txn_do( sub {
            my $post = $c->model('DBIC::Posts')->create({
                thread_id => $thread->id,
                user_id   => $c->user->obj->id,
                time      => time,
                format    => 'bbcode',
                content   => $parsed_message,
            });
            # update thread's last-post stats
            $thread->last_post_id( $post->id );
            $thread->last_post_time( time );
            $thread->post_count( $thread->post_count + 1 );
            $thread->update;
            # update forum's last-post stats
            $thread->forum->last_post_id( $post->id );
            $thread->forum->post_count( $thread->forum->post_count + 1 );
            $thread->forum->update;
            # update user's postcount
            $c->user->obj->post_count( $c->user->post_count + 1 );
            $c->user->obj->update;
            return $post;
        } );
    }

    # finito!
    # Latiedit: this should link to post/ urls.
    $c->res->redirect( $c->uri('Forum', 'post', $post->id) );
}

=head2 post_preview

=cut

sub post_preview : Private {
    my ($self, $c, $thread) = @_;
    my $s = $c->stash;

    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
    if (@bbcode_errors) {
        $c->vee_abort("Your post contains invalid bbcode.  Please go back and fix it.");
    }
    $parsed_message = Vee::Utils::fix_newlines( $parsed_message );
    
    my $rows = $c->site_opts->{page_sizes}{posts_preview};
    my $offset = $c->model('DBIC::Posts')->count({ thread_id => $thread->id }, { order_by => 'me.time ASC' } );
    $offset = $offset - $rows;

    my $posts_rs = $c->model('DBIC::Posts')->search({ thread_id => $thread->id }, {
        order_by => 'me.time ASC',
        offset   => $offset,
        rows     => $rows
    } );

    # form generation stuff
    my $reply_fields = {
        content => { type => 'textarea', rows => '10', cols => '100' },
        id => { type => 'hidden' },
    };
    
    my $form = new Vee::Form(
        id => 'reply',
        fields => $reply_fields,
        params => $c->req->params,
        copy_params => 1,
    );
    $form->force( id => $c->req->params->{id} );
    
    $s->{template}    = 'forum/thread/preview.tt';
    $s->{extra_css}   = [qw/forum bbcode/];
    $s->{posts_rs}    = $posts_rs;
    $s->{form}        = $form;
    $s->{tid}         = $c->req->params->{id};
    $s->{text}        = $parsed_message;
    $s->{page_title}  = "[PREVIEW] Reply to " . $thread->subject . " - Forums";
    $s->{page_header} = "Preview Reply to " . $thread->subject;
    $s->{user}        = $c->user->obj;
}

=head2 thread

=cut

sub thread : Local : Args(0) {
    my ($self, $c) = @_;
    
    $c->vee_abort('No forum id specified.  This should not happen.  Sorry?') unless $c->req->params->{id};

    my $forum = $c->model('DBIC::Forums')->find( $c->req->params->{id} )
        or $c->vee_abort('There is no forum with an id of ', $c->req->params->{id}, '.  It may have been deleted while you were typing?');

    if (!can_thread($c, $forum)) {
        $c->vee_abort('You do not have permission to create threads in this forum.');
    }

    # TODO: make these redir to an actual post page when one exists
    $c->vee_abort("You must enter a message.") unless $c->req->params->{content} =~ /\S/;
    $c->vee_abort("You must enter a subject.") unless $c->req->params->{subject} =~ /\S/;
    
    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode( $c->req->params->{content} );
    if (@bbcode_errors) {
        $c->detach('thread_preview');
    } 

    if ('preview' eq lc $c->req->params->{submit}) {
        $c->detach('thread_preview');
    }
    
    my $subject = $c->req->params->{subject};
    $subject =~ s/\x0d\x0a|\x0a|\x0d/ /g;
    $subject = Vee::Utils::cleanse($subject);
    my $blurb = $c->req->params->{blurb};
    $blurb =~ s/\x0d\x0a|\x0a|\x0d/ /g;
    $blurb = Vee::Utils::cleanse($blurb);

    # create the thread
    my $thread = $c->model('DBIC')->schema->txn_do( sub {
        my $thread = $c->model('DBIC::Threads')->create({
            forum_id       => $forum->id,
            subject        => $subject,
            first_post_id  => 0,
            last_post_id   => 0,
            last_post_time => time,
            post_count     => 1,
            blurb          => $blurb,
        });
        # create the post
        my $post = $c->model('DBIC::Posts')->create({
            thread_id => $thread->id,
            user_id   => $c->user->obj->id,
            time      => time,
            format    => 'bbcode',
            content   => Vee::Utils::fix_newlines( $parsed_message ),
        });
        # update thread's last-post stats
        $thread->first_post_id( $post->id );
        $thread->last_post_id( $post->id );
        $thread->update;
        # update forum's last-post stats
        $forum->last_post_id( $post->id );
        $forum->post_count( $forum->post_count + 1 );
        $forum->thread_count( $forum->thread_count + 1 );
        $forum->update;
        # update user's postcount
        $c->user->obj->post_count( $c->user->post_count + 1 );
        $c->user->obj->update;
        return $thread;
    } );

    # finito!
    $c->res->redirect( $c->uri('Forum', 'thread', $thread->id) );
}

=head2 thread_preview

=cut

sub thread_preview : Private {
    my ($self, $c) = @_;
    my $s = $c->stash;
    
    # Set up some variables?
    my $subject = $c->req->params->{subject};
    my $blurb   = $c->req->params->{blurb};
    my $content = $c->req->params->{content};
    my $forum = $c->model('DBIC::Forums')->find( $c->req->params->{id} )
        or $c->vee_abort('There is no forum with an id of ', $c->req->params->{id}, '.  It may have been deleted while you were typing?');
    
    if (!can_thread($c, $forum)) {
        $c->vee_abort('You do not have permission to create threads in this forum.');
    }
    
    my ($parsed_message, @bbcode_errors) = Vee::BBCode::validate_bbcode($content);
    if (@bbcode_errors) {
        $c->vee_abort("Your post contains invalid bbcode.  Please fix it.");
    }
    
    # form generation stuff
    my $reply_fields = {
        content => { type => 'textarea', rows => '10', cols => '100' },
        id => { type => 'hidden' },
        subject => { type => 'text', maxlength => 48 },
        blurb => { type => 'text', maxlength => 96 },
    };
    
    my $form = new Vee::Form(
        id => 'reply',
        fields => $reply_fields,
        params => $c->req->params,
        copy_params => 1,
    );
    $form->force( id => $c->req->params->{id} );
    
    $s->{extra_css}   = 'forum';
    $s->{form}        = $form;
    $s->{fid}         = $c->req->params->{id};
    $s->{subject}     = $subject;
    $s->{text}        = $parsed_message;
    $s->{blurb}       = $blurb;
    $s->{page_title}  = "[PREVIEW] $subject - Forums";
    $s->{page_header} = "Preview New Thread";
    $s->{template}    = 'forum/preview.tt';
    $s->{user}        = $c->user->obj;
}

=head1 AUTHOR

Maintainer: Alex "Eevee" Munroe (C<veekun@veekun.com>)

See the included F<AUTHORS> file for a full list of contributers.

=head1 LICENSE

See the included F<LICENSE> file.

=cut

1;
