package Catalyst::Plugin::RapidApp::AuthCore::PlugHook;
use Moose::Role;
use namespace::autoclean;

use RapidApp::Include qw(sugar perlutil);

=pod

=head1 DESCRIPTION

Plugin class seprated out of Catalyst::Plugin::RapidApp::AuthCore so
it can be loaded as a *plugin* (not a role) **AFTER** the other 
required Authentication and Session plugins. This is needed to overcome
load ordering issues. 'finalize_session' below doesn't exist until
these plugins are loaded, and since AuthCore handles loading them, it
can't also define the around (chickin/egg issue)

=cut


# ---- FIXME  FIXME  FIXME (2013-08-25 by HV) ----
#
# The sole purpose of this class is to make session extending (expires)
# work. This is supposed to happen automatically, and does if the Auth/Session
# plugins are loaded in the manner intended in the main app class:
#
#   use Catalyst qw(
#     Authentication
#     Authorization::Roles
#     Session
#     Session::State::Cookie
#     Session::Store::DBIC
#   );
#
# Or later in:
#
#   __PACKAGE__->setup(qw(
#     Authentication
#     Authorization::Roles
#     Session
#     Session::State::Cookie
#     Session::Store::DBIC
#   ));
#
# However, for RapidApp, we obviously don't want the end developer to have to do 
# that. We want them to just do:
#
#   with 'Catalyst::Plugin::RapidApp::AuthCore';
#
# and have it handle loading these plugins... This has been a struggle to
# get to work right. AuthCore handles loading the plugins 'before'
# $c->setup_dispatcher() because that is what is called immediately after
# $c->setup_plugins() in Catalyst.pm, and so it should be the earliest
# place to do it and have it work the same if AuthCore is loaded as a role
# using 'with' or loaded using the older use Catalyst @plg/__PACKAGE__->setup(@plg)
# syntax... (since everything before that point is before the plugin is loaded).
# 
# It is not that I want to load it at this point, it is just that this is the
# best point I have found to do it -- Is there some totally different place
# or way to do this?
#
# It seems to work... ***almost***  ... Something is not quite right with the
# resulting state, the example being the broken extending of sessions which I
# am manually addressing below. Everything else seems to work and I don't know
# why or where or how things end up different. I have tried lots of other 
# hook locations, like overriding '$c->arguments' and manually pushing the
# plugin list into it, (which works only for loading using 'with', but it is
# still broken in the same way). 

# I don't understand the problem. It appears that certain methods just don't
# exist and/or don't get called. I've dumped mro::get_linear_isa($c) and it
# appears to come out the same, so I don't understand why that would be. I
# still don't fully undertand all the mro/MI/setup that works under the hood,
# and I think that is what is keeping me from figuring things out.
#
# Here is an example of my lack of understanding, and what I think is related
# to the problem:
#
# If I try to use a normal sub with next::method, instead of 'around' below, 
# this gets thrown:
#  Caught exception in engine "No next::method 'finalize_session' found for ...
#
# Could it have to do with mixing method overrides with around and next::method
# style? It looks like the point where it might break, in following the Auth/Session
# plugins code, which seem to point back and forth at eachother in a maze, is that many
# methods, such as 'extend_session_id', return with maybe::next::method, which 
# might explain the silently broken functionality, but still not *why* that is...
#
# I am putting this on the shelf for now, since I have a workaround below for this
# particular problem, but I am very concerned that my lack of understanding of these
# internals could be leading to other, deep, dark broken things that just haven't
# been noticed...

around 'finalize_session' => sub {
  my $orig = shift;
  my $c = shift;
  
  if($c->_user) {
    my $expires = $c->session_expires;
    my $sid = $c->sessionid;
    $c->store_session_data( "expires:$sid" => $expires );
  }

  $c->$orig(@_);
};

1;

