package Mojolicious::Plugin::RoutesAuthDBI::Guest;
use Mojo::Base -base;#'Mojolicious::Plugin::Authentication'
use Mojolicious::Plugin::RoutesAuthDBI::Util qw(json_enc json_dec);


has [qw(session_key stash_key app plugin model)];

sub new {
  state $self = shift->SUPER::new(@_);
}

sub current {# Fetch the current guest object from the stash - loading it if not already loaded
  my ($self, $c) = @_;
  
  my $stash_key = $self->stash_key;
  
  $self->_loader($c)
    unless
      defined($c->stash($stash_key))
      && ($c->stash($stash_key)->{no_guest}
        || defined($c->stash($stash_key)->{guest}));

  my $guest_def = defined($c->stash($stash_key))
                    && defined($c->stash($stash_key)->{guest});

  return $guest_def ? $c->stash($stash_key)->{guest} : undef;
}

# Unconditionally load the guest based on id in session
sub _loader {
  my ($self, $c) = @_;
  my $gid = $c->session($self->session_key);
  
  my $guest = $self->load($gid)
    if defined $gid;

  if ($guest) {
      $c->stash($self->stash_key => { guest => $guest });
  }
  else {
      # cache result that guest does not exist
      $c->stash($self->stash_key => { no_guest => 1 });
  }
}

sub load {
  my ($self, $gid) = @_;
  
  my $guest = $self->model->get_guest($gid);
  
  if ( $guest && $guest->{id}) {
    my $json = json_dec(delete $guest->{data})
      if $guest->{data};
  
    @$guest{ keys %$json } = values %$json
      if $json;
    
    $self->app->log->debug("Success loading guest by id=$gid");
    return $guest;
  }
  $self->app->log->debug("Failed loading guest by id=$gid");
  
  return undef;
}

 sub reload {
  my ($self, $c) = @_;
  # Clear stash to force a reload of the guest object
  delete $c->stash->{$self->stash_key};
  return $self->current($c);
}

sub is_guest {
  my ($self, $c) = @_;
  return defined($self->current($c)) ? 1 : 0;
}

sub logout {
  my ($self, $c) = @_;
  delete $c->stash->{$self->stash_key};
  delete $c->session->{$self->session_key};
}

 sub store {# new guest
    my ($self, $c, $data) = @_;
    
    $data ||= {};
    $data->{headers} = $c->req->headers->to_hash(1);
    $data->{IP} = $c->tx->remote_address;

    my $guest = $self->model->store(json_enc($data));
    $c->session($self->session_key => $guest->{id});
    $c->stash($self->stash_key => { guest => $guest });
    
    return $guest;
}


1;

=pod

=encoding utf8

Доброго всем



=head1 Mojolicious::Plugin::RoutesAuthDBI::Guest

¡ ¡ ¡ ALL GLORY TO GLORIA ! ! !

=head1 NAME

Mojolicious::Plugin::RoutesAuthDBI::Guest - session for guests. Store guests in separate DBI table.

=head1 SYNOPSIS

    $app->plugin('RoutesAuthDBI', 
        ...
        guest => {< options list below >},
        ...
    );

=head1 OPTIONS

=over 4

=item * B<namespace> - default 'Mojolicious::Plugin::RoutesAuthDBI',

=item * B<module> - default 'Guest' (this module),

=item * B<session_key> - session storage of guest data. Default 'guest_data'.

=item * B<stash_key> - 

=item * B<> - 

=back

=head1 METHODS

=head2 current($controller)

Get current guest hashref by session and undef overwise.

  my $guest = $c->access->plugin->guest->current($c);

=head2 store($controller, $data)

Store guest data in DB table and set session_key. Headers of request save in "data" column.

  $c->access->plugin->guest->store($c, {"Glory"=>"is ♥ for me"});

=head2 is_guest($controller)

True if current session of guest.

  if( $c->access->plugin->guest->is_guest($c) ) {...}

=head2 load($id)

Loads guest data from DB table by its ID row. JSON column "data" will expand.

  my $data = $c->access->plugin->guest->load($id);

=head2 reload($controller)

Cleanup stash and reload guest data.

  my $guest = $c->access->plugin->guest->reload($c);

=head1 SEE ALSO

L<Mojolicious::Plugin::Authentication>

=head1 AUTHOR

Михаил Че (Mikhail Che), C<< <mche [on] cpan.org> >>

=head1 BUGS / CONTRIBUTING

Please report any bugs or feature requests at L<https://github.com/mche/Mojolicious-Plugin-RoutesAuthDBI/issues>. Pull requests welcome also.

=head1 COPYRIGHT

Copyright 2016+ Mikhail Che.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=cut
