sub CustomFieldValue {
    my ($self, $id) = @_;
    eval {
	$self->CustomFieldValues(
	    RT::CustomField->NameToId($id)
	)->First->Content
    };
}

sub SetCustomFieldValue {
    my ($self, $id, $value) = @_;
    eval {
	$self->CustomFieldValues(
	    RT::CustomField->NameToId($id)
	)->First->SetContent($value)
    };
}

sub FirstContent {
    my $self = shift;
    my $Transactions = $self->Transactions or return;
    while (my $Transaction = $Transactions->Next) {
        return $Transaction->Content if $Transaction->ContentObj;
    }
    return '';
}

sub LastContent {
    my $self = shift;
    $self = $self->OriginObj || $self;
    my $Transactions = $self->Transactions or return;
    $Transactions->OrderBy( FIELD => 'Created', ORDER => 'DESC' );
    while (my $Transaction = $Transactions->Next) {
        return $Transaction->Content if $Transaction->ContentObj;
    }
    return '';
}

# --- Code Below Aren't Meant For Merge --- #

# {{{ sub PrettyPrint 

=head2 PrettyPrint

    Pretty prints the ticket content for mail user's consumption.

=cut

sub PrettyPrint {
    my ($self, $UserObj) = @_;
    $UserObj ||= eval { $self->FirstRequestor };

    my $CustomFields = $self->QueueObj->CustomFields;
    my @entry_fields;
    my (@out, $final_out);

    while ( my $cf = $CustomFields->Next ) {
	next if $cf->Attribute('OnCreate') eq 'hidden'
	    and $cf->Attribute('OnUpdate') eq 'hidden';

	if ($cf->IsEntry) {
	    push @entry_fields, $cf;
	    next;
	}
	elsif ($cf->IsLabel) {
	    next;
	}

	push @out, $cf->DescriptionOrName;

	# Value {{{
	my $out = '';
	my $Values = $self->CustomFieldValues($cf->id);

	if ($cf->Type =~ /^Freeform/) {
	    while (my $Value = $Values->Next()) {
		$out .= $Value->Content . "\n";
	    }
	}
	elsif ($cf->Type =~ /^Select(?:Single|Multiple)$/) {
	    my $CustomFieldValues = $cf->Values();
	    while (my $value = $CustomFieldValues->Next) {
		next unless $Values->HasEntry($value->Name);
		$out .= $value->Description . "\n";
	    }
	}
	elsif ($cf->Type eq 'SelectExternal') {
	    my $sql = $UserObj->ext_table('hrms_userdefined_field')->{$cf->Description}->{
		'hrms_userdefined_field_sql'
	    };
	    my $SubHash = {};
	    if ($sql) {
		$sql =~ s/\$(\w+)/$UserObj->val($1)/ge;
		$SubHash = $UserObj->get_hash($sql);
	    }
	    my $selected;
	    foreach my $v (sort { $a <=> $b } keys %$SubHash) { 
		next unless $Values->HasEntry($v);
		$out .= $SubHash->{$v} . "\n";
	    }
	}

	push @out, $out;
	# }}}
    }

    my (@head, @body);
    while (my ($k, $v) = splice(@out, 0, 2)) {
	push @head, $k;
	chomp $v;
	$v =~ s/\n/,/g;
	push @body, $v;
    }
    $final_out .= $self->_ShowTable(\@head, \@body);

    # Entries
    my @table;
    if (@entry_fields) {
	my @Current;
	my $LastIndex = -1;
	foreach my $cf (@entry_fields) {
	    if ($cf->Type eq 'EntryExternal') {
		my $sql = $UserObj->ext_table(
		    'hrms_userdefined_field'
		)->{$cf->Description}->{ 'hrms_userdefined_field_sql' };
		my $SubHash = {};
		if ($sql) {
		    $sql =~ s/\$(\w+)/$UserObj->val($1)/ge;
		    $SubHash = $UserObj->get_hash($sql);
		}
		push @Current, [ map {
		    $SubHash->{$_->Content}
		} @{$self->CustomFieldValues($cf->Id)->ItemsArrayRef} ];
	    }
	    elsif ($cf->Type eq 'EntrySelect') {
		my $CustomFieldValues = $cf->Values;
		push @Current, [ map {
		    my $description = '';
		    $CustomFieldValues->GotoFirstItem;
		    while (my $value = $CustomFieldValues->Next) {
			next unless $value->Name eq $_->Content;
			$description = $value->Description || $value->Name;
			last;
		    }
		    $description;
		} @{$self->CustomFieldValues($cf->Id)->ItemsArrayRef} ];
	    }
	    else {
		push @Current, [ map {
		    $_->Content
		} @{$self->CustomFieldValues($cf->Id)->ItemsArrayRef} ];
	    }

	    $LastIndex = $#{$Current[-1]} if $#{$Current[-1]} > $LastIndex;
	}

	push @table, [ map $_->DescriptionOrName, @entry_fields ];

	foreach my $row (0 .. $LastIndex) {
	    push @table, [ map { $_->[$row] } @Current ];
	}

	$final_out .= $self->_ShowTable(@table);
    }

    if ($self->Transactions->First->ContentObj) {
	# no longer wrapping since it may break the content
	my $content = $self->Transactions->First->Content;
	$content =~ s/^/    /mg;
	$final_out .= $content;
    }

    return $final_out;
}

sub _ShowTable {
    my $self = shift;

    local $^W;
    require Data::ShowTable;
    # $Data::ShowTable::Max_List_Width = 80;

    my $out = '';
    *Data::ShowTable::out = sub {
	chomp(my $text = shift); $out .= sprintf("$text\n", @_)
    } if defined *Data::ShowTable::out;
    *Data::ShowTable::put = sub {
	$out .= sprintf(shift, @_)
    } if defined *Data::ShowTable::put;

    my $array = \@_;
    my $cnt;
    Data::ShowTable::ShowListTable(
	+shift, [ ], [ ], sub {
	    if ($_[0]) { $cnt = 0; return 1 }
	    return if $cnt > $#{$array};
	    return @{$array->[$cnt++]};
	}
    );

    $out =~ s/^/        /mg if length($out);
    return $out;
}

# }}}

sub RequestorNames {
    my $self = shift;

    unless ( $self->CurrentUserHasRight('ShowTicket') ) {
        return undef;
    }

    return join( ', ',
	map { $_->Name }
	@{$self->Requestors->UserMembersObj->ItemsArrayRef||[]}
    );
}

sub IsOverdue {
    my $self = shift;
    my $due = $self->DueObj->Unix or return;
    return ($due > 0 and $due < time());
}


# XXX - These should be rewritten using Attributes! - XXX
sub OriginTicket { $_[0]->__Value('Resolution') }
sub OriginQueue  { $_[0]->__Value('IssueStatement') }
sub OriginObj	 {
    my $self = shift;
    my $obj  = RT::Ticket->new($self->CurrentUser);
    $obj->Load($self->OriginTicket);
    return unless $obj->Id;
    return $obj;
}

sub SetOriginTicket { $_[0]->__Set(Field => 'Resolution', Value => $_[1] ) }
sub SetOriginQueue  { $_[0]->__Set(Field => 'IssueStatement', Value => $_[1]) }
sub SetOriginObj    { 
    my ($self, $obj) = @_;
    $self->SetOriginTicket($obj->Id);
    $self->SetOriginQueue($obj->QueueObj->Id);
}

1;
