=head1 NAME

EPrints::Plugin::Screen

=cut

package EPrints::Plugin::Screen;

# Top level screen.
# Abstract.
# 

use strict;

our @ISA = qw/ EPrints::Plugin /;

sub new
{
	my( $class, %params ) = @_;

	$params{actions} = exists $params{actions} ? $params{actions} : [];
	$params{session} = exists $params{session} ? $params{session} : $params{processor}->{session};

	# flag to indicate that it takes some effort to make this screen, so
	# don't make it up as a tab. eg. EPrint::History.
	$params{expensive} = exists $params{expensive} ? $params{expensive} : 0; 

	return $class->SUPER::new(%params);
}

sub properties_from
{
	my( $self ) = @_;

}

sub redirect_to_me_url
{
	my( $self ) = @_;

	return $self->{processor}->{url}."?screen=".$self->{processor}->{screenid};
}

sub render
{
	my( $self ) = @_;

	my $phraseid = substr(__PACKAGE__, 9);
	$phraseid =~ s/::/\//g;
	$phraseid .= ":no_render_subclass";

	return $self->{session}->html_phrase( $phraseid, screen => $self->{session}->make_text( $self ) );
}

sub render_links
{
	my( $self ) = @_;

	return $self->{session}->make_doc_fragment;
}

sub register_furniture
{
	my( $self ) = @_;

	return $self->{session}->make_doc_fragment;
}

sub register_error
{
	my( $self ) = @_;

	$self->{processor}->add_message( "error", $self->{session}->html_phrase( 
		"Plugin/Screen:screen_not_allowed",
		screen=>$self->{session}->make_text( $self->{processor}->{screenid} ) ) );
}

=item @params = $screen->hidden_bits()

Returns a key-value list of values that must be set when referring to this screen.

At the top-level this is just the 'screen' id.

=cut

sub hidden_bits
{
	my( $self ) = @_;

	return(
		screen => $self->get_subtype
	);
}

sub render_hidden_bits
{
	my( $self, $idsuffix ) = @_;

	my $chunk = $self->{session}->make_doc_fragment;

	my @params = $self->hidden_bits;
	for(my $i = 0; $i < @params; $i+=2)
	{
		my $name = $params[$i];
		my $value = $params[$i+1];
		my $id = $idsuffix ? $name . "_" . $idsuffix : $name;
		$chunk->appendChild( $self->{session}->render_hidden_field( 
				$name,
				$value, 
				$id
			) );
	}

	return $chunk;
}

sub wishes_to_export
{
	my( $self ) = @_;

	return 0;
}

sub export
{
	my( $self ) = @_;

	print "Needs to be subclassed\n";
}
sub export_mimetype
{
	my( $self ) = @_;

	return "text/plain";
}

	
sub render_form
{
	my( $self, $idsuffix ) = @_;

	my $form = $self->{session}->render_form( "post", $self->{processor}->{url}."#t" );

	$form->appendChild( $self->render_hidden_bits( $idsuffix ) );

	return $form;
}

sub about_to_render 
{
	my( $self ) = @_;
}

sub obtain_edit_lock
{
	my( $self ) = @_;

	return $self->obtain_lock;
}

sub obtain_view_lock
{
	my( $self ) = @_;

	return $self->obtain_lock;
}

sub obtain_lock
{
	my( $self ) = @_;
	
	return 1;
}

sub can_be_viewed
{
	my( $self ) = @_;

	return 1;
}

sub allow_action
{
	my( $self, $action_id ) = @_;
	my $ok = 0;
	foreach my $an_action ( @{$self->{actions}} )
	{
		if( $an_action eq $action_id )
		{
			$ok = 1;
			last;
		}
	}

	return( 0 ) if( !$ok );

	my $fn = "allow_".$action_id;
	return $self->$fn;
}

sub render_tab_title
{
	my( $self ) = @_;

	return $self->render_title;
}

sub from
{
	my( $self ) = @_;

	my $action_id = $self->{processor}->{action};

	return if( !defined $action_id || $action_id eq "" );

	return if( $action_id eq "null" );

	# If you hit reload after login you can cause a
	# login action, so we'll just ignore it.
#	return if( $action_id eq "login" );

	my $ok = 0;
	foreach my $an_action ( @{$self->{actions}} )
	{
		if( $an_action eq $action_id )
		{
			$ok = 1;
			last;
		}
	}

	if( !$ok )
	{
		$self->{processor}->add_message( "error",
			$self->{session}->html_phrase( 
	      			"Plugin/Screen:unknown_action",
				action=>$self->{session}->make_text( $action_id ),
				screen=>$self->{session}->make_text( $self->{processor}->{screenid} ) ) );
		return;
	}

	if( $self->allow_action( $action_id ) )
	{
		my $fn = "action_".$action_id;
		$self->$fn;
	}
	else
	{
		$self->{processor}->action_not_allowed( 
			$self->html_phrase( "action:$action_id:title" ) );
	}
}

sub allow
{
	my( $self, $priv, $item ) = @_;

	return 1 if( $self->{session}->allow_anybody( $priv ) );
	return 0 if( !defined $self->{session}->current_user );
	return $self->{session}->current_user->allow( $priv, $item );
}


# these methods all could be properties really


sub matches 
{
	my( $self, $test, $param ) = @_;

	return $self->SUPER::matches( $test, $param );
}

sub render_title
{
	my( $self ) = @_;

	return $self->html_phrase( "title" );
}

=item @screen_opts = $screen->list_items( $list_id, %opts )

Returns a list of screens that appear in list $list_id ordered by their position.

Each screen opt is a hash ref of:

	screen - screen plugin
	screen_id - screen id
	position - position (positive integer)
	action - the action, if this plugin is for an action list

Incoming opts:

	filter => 1 or 0 (default 1)
	params => {}

=cut

sub list_items
{
	my( $self, $list_id, %opts ) = @_;

	return $self->{processor}->list_items( $list_id, %opts );
}	

sub action_allowed
{
	my( $self, $item ) = @_;
	my $who_allowed;
	if( defined $item->{action} )
	{
 		$who_allowed = $item->{screen}->allow_action( $item->{action} );
	}
	else
	{
		$who_allowed = $item->{screen}->can_be_viewed;
	}

	return 0 unless( $who_allowed & $self->who_filter );
	return 1;
}

sub action_list
{
	my( $self, $list_id ) = @_;

	my @list = ();
	foreach my $item ( $self->list_items( $list_id ) )
	{
		next unless $self->action_allowed( $item );

		push @list, $item;
	}

	return @list;
}


sub who_filter { return 255; }

sub get_description
{
	my( $self, $params ) = @_;
	my $description;
	if( defined $params->{action} )
	{
		my $action = $params->{action};
		$description = $params->{screen}->html_phrase( "action:$action:description" );
	}
	else
	{
		$description = $params->{screen}->html_phrase( "description" );
	}
	return $description;
}

=item $url = $screen->action_icon_url( $action )

Returns the relative URL to the $action icon for this screen.

=cut

sub action_icon_url
{
	my( $self, $action ) = @_;

	my $icon = $self->{session}->get_repository->get_conf( "plugins", $self->{id}, "actions", $action, "icon" );
	if( !defined $icon ) 
	{
		$icon = $self->{action_icon}->{$action};
	}

	return undef if !defined $icon;

	my $url = $self->{session}->get_url( path => "images", $icon );

	return $url;
}

=item $frag = $screen->render_action_link()

Returns a link to this screen.

=cut

sub render_action_link
{
	my( $self, %opts ) = @_;

	my $uri = URI->new( $self->{session}->config( "rel_cgipath" ) . "/users/home" );
	$uri->query_form(
		screen => substr($self->{id},8),
	);

	if ( exists $opts{uri} )
	{
		$uri = $opts{uri};
		delete $opts{uri};
	}

	my $title = undef;
	if ( exists $opts{link_title} )
	{
		$title = $opts{link_title};
		delete $opts{link_title} ;
	}
	else
	{
		$title = $self->render_title;
	}

	my $class = $opts{class} if defined $opts{class}; 
	my $link = $self->{session}->render_link( $uri, undef, %opts );
	$link->appendChild( $self->render_title );

	my @opts = (); # for iteration in xml phrase
        my $item = {
		class => $class,
		uri => $uri,
		opts => [],
		title => $title,
        };

        for my $opt_val ( keys %opts )
        {
                push @{ $item->{opts} }, { name => $opt_val, value => $opts{$opt_val} };
        }

	return $self->{session}->template_phrase( "view:EPrints/Plugin/ScreenProcessor:render_action_link", { item => $item });
}

sub render_action_icon
{
	my( $self, $params ) = @_;

	return $self->_render_action_aux( $params, 1 );
}

sub render_action_button
{
	my( $self, $params ) = @_;

	return $self->_render_action_aux( $params, 0 );
}

sub _render_action_aux
{
	my( $self, $params, $asicon ) = @_;
	
	my $session = $self->{session};
	
	my $method = "GET";	
	if( defined $params->{action} )
	{
		$method = "POST";
	}

	my @query = (screen => substr( $params->{screen_id}, 8 ));

	my $hidden = $params->{hidden};
	if( ref($hidden) eq "ARRAY" )
	{
		foreach my $id ( @$hidden )
		{
			push @query, $id => $self->{processor}->{$id};
		}
	}
	else
	{
		foreach my $id (keys %$hidden)
		{
			push @query, $id => $hidden->{$id};
		}
	}
	my( $action, $title, $icon );
	if( defined $params->{action} )
	{
		$action = $params->{action};
		$title = $params->{screen}->phrase( "action:$action:title" );
		$icon = $params->{screen}->action_icon_url( $action );
	}
	else
	{
		$action = "";
		$title = $params->{screen}->phrase( "title" );
		$icon = $params->{screen}->icon_url();
	}
	
	my $path = $session->current_url( path => "cgi" ) . "/users/home";

	my $frag;

	if( $method eq "GET" && defined $icon && $asicon )
	{
		push @query, "_action_$action" => 1 if length($action);
		my $uri = URI->new( $path );
		$uri->query_form( @query );
		$frag = $session->render_link( $uri );
		if( defined $icon && $asicon )
		{
			$frag->appendChild( $session->make_element( "img",
				src=>$icon,
				alt=>$title,
				title=>$title . $session->phrase( "Plugin/Screen:render_action_img_suffix" ),
				class=>"ep_form_action_icon",
				role=>"button",
			) );
		}
		# never called because mixing <input> and <href> is ugly
		else
		{
			$frag->setAttribute( class => "ep_form_action_button" );
			$frag->setAttribute( role => "button" );
			$frag->appendChild( $session->make_text( $title ) );
		}
	}
	else
	{
		$frag = $session->render_form( $method, $path );
		foreach my $i (0..$#query)
		{
			next if $i % 2;
			my $hidden_name = $query[$i];
			my $hidden_value = $query[$i+1];
			my $hidden_id = $hidden_name . "_".$hidden_value;
			$hidden_id .= "_" . $params->{screen_id} unless $hidden_name eq "screen";
			$hidden_id .= "_" . $params->{action} if defined $params->{action} && $hidden_name ne "action";
			$hidden_id .= defined $params->{idsuffix} ? "_" .$params->{idsuffix} : "";
			$frag->appendChild( $session->render_hidden_field(
				$hidden_name, $hidden_value, $hidden_id  ) );
		}
		if( defined $icon && $asicon )
		{
			$frag->appendChild( 
				$session->make_element(
					"input",
					type=>"image",
					class=>"ep_form_action_icon",
					role=>"button",
					($action ? (name=>"_action_$action") : ()),
					src=>$icon,
					title=>$title,
					alt=>$title,
					value=>$title ));
		}
		else
		{
			$frag->appendChild( 
				$session->render_button(
					class=>"ep_form_action_button",
					role=>"button",
					($action ? (name=>"_action_$action") : ()),
					value=>$title ));
		}
	}

	return $frag;
}

sub render_action_button_if_allowed
{
	my( $self, $params, $hidden ) = @_;

	if( $self->action_allowed( $params ) )
	{
		return $self->render_action_button( { %$params, hidden => $hidden } ); 
	}
	else
	{
		return $self->{session}->make_doc_fragment;
	}
}

sub render_action_list
{
	my( $self, $list_id, $hidden ) = @_;

	my $repo = $self->repository;

	my( @actions, @definitions );
	foreach my $params ($self->action_list( $list_id ))
	{
		push @actions, $self->render_action_button( { %$params, hidden => $hidden, idsuffix => $list_id } );
		push @definitions, $self->get_description( $params );
	}

	return $repo->xhtml->action_definition_list( \@actions, \@definitions, id=>$list_id );
}


sub render_action_list_bar
{
	my( $self, $list_id, $hidden ) = @_;

	my $repo = $self->repository;

	my @actions;
	foreach my $params ($self->action_list( $list_id ))
	{
		push @actions, $self->render_action_button( { %$params, hidden => $hidden, idsuffix => $list_id } );
	}

	return $self->repository->template_phrase( "view:EPrints/Plugin/Screen:render_action_list_bar", { item => {
		list_id => $list_id,
		action_list => $repo->xhtml->action_list( \@actions ),
		hidden => $hidden,
	} } );
}


sub render_action_list_icons
{
	my( $self, $list_id, $hidden ) = @_;

	my $item = {
		columns => []
	};

	my @idfields = ( 'dataobj', 'eprintid' );
	my $idsuffix;
	foreach ( keys %$hidden )
	{
		if ( grep( /^$_$/, @idfields ) )
		{
			$idsuffix = $list_id . "_" . $hidden->{$_};
			last;
		}
	}

	foreach my $params ($self->action_list( $list_id ))
	{
		push @{ $item->{columns} }, {
			icon => $self->render_action_icon( { %$params, hidden => $hidden, idsuffix => $idsuffix } )
		};
	}

	return $self->repository->template_phrase( "view:EPrints/Plugin/Screen:action_list_icons", { item => $item } );
}

1;

		
		

=head1 COPYRIGHT

=begin COPYRIGHT

Copyright 2023 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.

http://www.eprints.org/eprints-3.4/

=end COPYRIGHT

=begin LICENSE

This file is part of EPrints 3.4 L<http://www.eprints.org/>.

EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.

EPrints 3.4 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.

=end LICENSE

