#!/usr/bin/perl
#
# This code was forked from the LiveJournal project owned and operated
# by Live Journal, Inc. The code has been modified and expanded by
# Dreamwidth Studios, LLC. These files were originally licensed under
# the terms of the license supplied by Live Journal, Inc, which can
# currently be found at:
#
# http://code.livejournal.org/trac/livejournal/browser/trunk/LICENSE-LiveJournal.txt
#
# In accordance with the original license, this code and all its
# modifications are provided under the GNU General Public License.
# A copy of that license can be found in the LICENSE file included as
# part of this distribution.

use strict;

package LJ::S2;

sub ReplyPage {
    my ( $u, $remote, $opts ) = @_;

    my $p = Page( $u, $opts );
    $p->{'_type'} = "ReplyPage";
    $p->{'view'}  = "reply";

    my $get = $opts->{'getargs'};

    my ( $entry, $s2entry ) = EntryPage_entry( $u, $remote, $opts );
    return if $opts->{'suspendeduser'};

    # reply page of suspended entry cannot be accessed by anyone, even entry poster
    if ( $entry && $entry->is_suspended ) {
        $opts->{suspendedentry} = 1;
        return;
    }

    # read-only users can't comment anywhere
    if ( $remote && $remote->is_readonly ) {
        $opts->{readonlyremote} = 1;
        return;
    }

    # no one can comment in a read-only journal
    if ( $u->is_readonly ) {
        $opts->{readonlyjournal} = 1;
        return;
    }

    return if $opts->{'handler_return'};
    return if $opts->{'redir'};
    return if $opts->{internal_redir};

    my $ditemid   = $entry->ditemid;
    my $replytoid = $get->{replyto} ? $get->{replyto} : 0;

    # canonical link to the entry or comment thread
    $p->{head_content} .= LJ::canonical_link( $entry->url, $replytoid );

    $p->{'head_content'} .= qq{
<script type="text/javascript" src="$LJ::JSPREFIX/md5.js"></script>
};

    LJ::need_res( LJ::S2::tracking_popup_js() );

    # include JS for quick reply, icon browser, and ajax cut tag
    my $handle_with_siteviews = $opts->{handle_with_siteviews_ref}
        && ${ $opts->{handle_with_siteviews_ref} };
    LJ::Talk::init_s2journal_js(
        iconbrowser => $remote && $remote->can_use_userpic_select,
        siteskin    => $handle_with_siteviews,
        noqr        => 1
    );

    if ( $u->should_block_robots || $entry->should_block_robots ) {
        $p->{'head_content'} .= LJ::robot_meta_tags();
    }

    $p->{'entry'} = $s2entry;
    LJ::Hooks::run_hook( 'notify_event_displayed', $entry );

    # setup the replying item
    my $replyto = $s2entry;
    my $editid  = $get->{edit} ? $get->{edit} : 0;
    my $parpost;
    my $parentcomment;

    my $comment;
    my %comment_values;
    if ($editid) {
        my $errref;
        $comment = LJ::Comment->new( $u, dtalkid => $editid );
        unless ($remote) {
            my $redir = LJ::eurl( LJ::create_url( undef, keep_args => 1 ) );
            $opts->{'redir'} = "$LJ::SITEROOT/?returnto=$redir&errmsg=notloggedin";
            return;
        }
        unless ( $comment->remote_can_edit( \$errref ) ) {
            if ($errref) {
                $opts->{status} = "403 Forbidden";
                return "<p>$errref</p>";
            }
            $opts->{'handler_return'} = 403;
            return;
        }

        $parpost = $comment->parent;

# for comments where the parent comment is deleted, we pretend the parent comment doesn't exist so the user can edit
        $parpost   = undef if $parpost && $parpost->is_deleted;
        $replytoid = $parpost ? $comment->parent->dtalkid : 0;

        $comment_values{editid}                = $editid;
        $comment_values{replyto}               = $replytoid;
        $comment_values{subject}               = $comment->subject_orig;
        $comment_values{body}                  = $comment->body_orig;
        $comment_values{subjecticon}           = $comment->prop('subjecticon');
        $comment_values{prop_opt_preformatted} = $comment->prop('opt_preformatted');
        $comment_values{prop_picture_keyword}  = $comment->userpic_kw;
        $comment_values{prop_editor}           = $comment->prop('editor');
    }

    if ($replytoid) {
        my $re_talkid = int( $replytoid >> 8 );
        my $re_anum   = $replytoid % 256;
        unless ( $re_anum == $entry->anum ) {
            $opts->{'handler_return'} = 404;
            return;
        }

        my $dtalkid = $re_talkid * 256 + $entry->anum;

        # FIXME: Why are we loading the comment manually when we do LJ::Comment->new below
        # and could do everything through there.
        my $sql =
              "SELECT jtalkid, posterid, state, datepost FROM talk2 "
            . "WHERE journalid=$u->{'userid'} AND jtalkid=$re_talkid "
            . "AND nodetype='L' AND nodeid="
            . $entry->jitemid;
        foreach my $pass ( 1, 2 ) {
            my $db = $pass == 1 ? LJ::get_cluster_reader($u) : LJ::get_cluster_def_reader($u);
            $parpost = $db->selectrow_hashref($sql);
            last if $parpost;
        }
        my $parentcomment = LJ::Comment->new( $u, jtalkid => $re_talkid );
        unless ( $parpost and $parpost->{'state'} ne 'D' ) {

            # FIXME: This is a hack. See below...

            $opts->{status} = "404 Not Found";
            return "<p>This comment has been deleted; you cannot reply to it.</p>";
        }
        if ( $parpost->{state} eq 'S' && !$parentcomment->visible_to($remote) ) {
            $opts->{'handler_return'} = 403;
            return;
        }
        if ( $parpost->{'state'} eq 'F' ) {

            # frozen comment, no replies allowed

            # FIXME: eventually have S2 ErrorPage to handle this and similar
            #    For now, this hack will work; this error is pretty uncommon anyway.
            $opts->{status} = "403 Forbidden";
            return "<p>This thread has been frozen; no more replies are allowed.</p>";
        }
        if ( $entry->is_suspended ) {
            $opts->{status} = "403 Forbidden";
            return "<p>This entry has been suspended; you cannot reply to it.</p>";
        }
        if ( $remote && $remote->is_readonly ) {
            $opts->{status} = "403 Forbidden";
            return "<p>You are read-only.  You cannot reply to this entry.</p>";
        }

        my $tt = LJ::get_talktext2( $u, $re_talkid );
        $parpost->{'subject'} = $tt->{$re_talkid}->[0];
        $parpost->{'body'}    = $tt->{$re_talkid}->[1];
        $parpost->{'props'} =
            LJ::load_talk_props2( $u, [$re_talkid] )->{$re_talkid} || {};

        if ( $parpost->{'props'}->{'unknown8bit'} ) {
            LJ::item_toutf8( $u, \$parpost->{'subject'}, \$parpost->{'body'}, {} );
        }

        my $datetime = DateTime_unix( LJ::mysqldate_to_time( $parpost->{'datepost'} ) );

        my $comment_userpic;
        my $s2poster;

        my $pu = $parentcomment->poster;
        if ($pu) {
            return $opts->{handler_return} = 403
                if $pu->is_suspended;    # do not show comments by suspended users
            $s2poster = UserLite($pu);

            my ( $pic, $pickw ) = $parentcomment->userpic;
            $comment_userpic = Image_userpic( $pu, $pic ? $pic->picid : 0, $pickw );
        }

        my $anon_comment = LJ::Talk::treat_as_anon( $pu, $u );
        LJ::CleanHTML::clean_comment(
            \$parpost->{'body'},
            {
                preformatted => $parentcomment->prop('opt_preformatted'),
                anon_comment => $anon_comment,
                nocss        => $anon_comment,
                editor       => $parentcomment->prop('editor'),
                datepost     => $parentcomment->{datepost},                 # for format guessing
                is_imported => defined $parentcomment->prop('import_source') ? 1 : 0,
            }
        );

        my $cmtobj = LJ::Comment->new( $u, dtalkid => $dtalkid );

        my $tz_remote;
        my $datetime_remote;
        my $datetime_poster;
        if ($remote) {
            my $tz = $remote->prop("timezone");
            $tz_remote = $tz ? eval { DateTime::TimeZone->new( name => $tz ); } : undef;
        }

        $datetime_remote = $tz_remote ? DateTime_tz( $cmtobj->unixtime, $tz_remote ) : undef;
        $datetime_poster =
            $parentcomment ? DateTime_tz( $cmtobj->unixtime, $parentcomment->poster ) : undef;

        my $replyargs = LJ::viewing_style_args(%$get);
        $replyto = {
            '_type'          => 'Comment',
            'subject'        => LJ::ehtml( $parpost->{'subject'} ),
            'text'           => $parpost->{'body'},
            'userpic'        => $comment_userpic,
            'poster'         => $s2poster,
            'journal'        => $s2entry->{'journal'},
            'metadata'       => {},
            'permalink_url'  => $cmtobj->url($replyargs),
            'depth'          => 1,
            'parent_url'     => $cmtobj->parent_url($replyargs),
            'threadroot_url' => $cmtobj->threadroot_url($replyargs),
            'time'           => $datetime,
            'system_time'    => $datetime,
            'time_remote'    => $datetime_remote,
            'time_poster'    => $datetime_poster,
            'tags'           => [],
            'talkid'         => $dtalkid,
            'link_keyseq'    => ['delete_comment'],
            'screened'       => $parpost->{'state'} eq "S" ? 1 : 0,
            'frozen'         => $parpost->{'state'} eq "F" ? 1 : 0,
            'deleted'        => $parpost->{'state'} eq "D" ? 1 : 0,
            'full'           => 1,
            timeformat24     => $remote && $remote->use_24hour_time,
            admin_post       => $cmtobj->admin_post ? 1 : 0,
        };

        # Conditionally add more links to the keyseq
        my $link_keyseq = $replyto->{'link_keyseq'};
        push @$link_keyseq, $replyto->{'screened'} ? 'unscreen_comment' : 'screen_comment';
        push @$link_keyseq, $replyto->{'frozen'}   ? 'unfreeze_thread'  : 'freeze_thread';
        push @$link_keyseq, "watch_thread"    if LJ::is_enabled('esn');
        push @$link_keyseq, "unwatch_thread"  if LJ::is_enabled('esn');
        push @$link_keyseq, "watching_parent" if LJ::is_enabled('esn');
        unshift @$link_keyseq, "edit_comment" if LJ::is_enabled('edit_comments');
    }

    $p->{'replyto'} = $replyto;

    $p->{'form'} = {
        '_type'      => "ReplyForm",
        '_remote'    => $remote,
        '_u'         => $u,
        '_ditemid'   => $ditemid,
        '_entry'     => $entry,
        '_parpost'   => $parpost,
        '_values'    => \%comment_values,
        '_styleopts' => $p->{_styleopts},
        '_thread'    => $get->{thread} || 0,
    };

    $p->{'isedit'} = $editid ? 1 : 0;

    return $p;
}

package S2::Builtin::LJ;

sub ReplyForm__print {
    my ( $ctx, $form ) = @_;
    my $remote  = $form->{'_remote'};
    my $u       = $form->{'_u'};
    my $parpost = $form->{'_parpost'};
    my $parent  = $parpost ? $parpost->{'jtalkid'} : 0;

    my $post_vars = DW::Request->get->post_args;
    $post_vars = $form->{_values}
        unless keys %$post_vars;    # _values only gets populated when editing comment. -NF

    $S2::pout->(
        LJ::Talk::talkform(
            {
                'journalu'   => $u,
                'parpost'    => $parpost,
                'replyto'    => $parent,
                'ditemid'    => $form->{'_ditemid'},
                'styleopts'  => $form->{_styleopts},
                'thread'     => $form->{_thread},
                'form'       => $post_vars,
                'do_captcha' => LJ::Talk::Post::require_captcha_test(
                    $remote, $u, $post_vars->{body}, $form->{'_entry'}
                )
            }
        )
    );

}

1;
