package BookmarksApp;

use strict;
use warnings;

use parent qw{Plack::Component};
use Plack::Util::Accessor qw{config _app _controller};

use YAML;
use Plack::Builder;
use Plack::Request;
use Router::Resource;

use Bookmarks::Controller;

sub prepare_app {
    my $self = shift;

    my $config = $self->config;

    my $router = router {
        resource '/' => sub {
            GET {
                # check for a uri param, and if there is one present,
                # see if a bookmark for that URI already exists; if so
                # redirect to that bookmark, and if not, show the form
                # to create a new bookmark
                if (defined $self->_controller->request->param('uri')) {
                    return $self->_controller->find_or_new;
                }

                # otherwise return a list
                return $self->_controller->list;
            };
            POST {
                # create the bookmark and redirect to the new bookmark's edit form
                return $self->_controller->create_and_redirect;
            };
        };

        resource '/list' => sub {
            GET {
                return $self->_controller->list;
            };
        };

        resource '/feed' => sub {
            GET {
                return $self->_controller->feed;
            };
        };

        resource '/{id}' => sub {
            GET {
                my ($env, $params) = @_;
                return $self->_controller->view($params->{id});
            };
            POST {
                my ($env, $params) = @_;
                return $self->_controller->update_and_redirect($params->{id});
            };
        };

        resource '/{id}/{field}' => sub {
            GET {
                my ($env, $params) = @_;
                return $self->_controller->view_field($params->{id}, $params->{field});
            };
        };
    };

    $self->_app(
        builder {
            enable_if { $_[0]->{REMOTE_ADDR} eq $config->{proxy_ip} } 'ReverseProxy'
                if $config->{proxy_ip};
            enable_if { $_[0]->{REQUEST_METHOD} ne 'GET' } 'Auth::Digest', (
                realm           => 'Bookmarks',
                secret          => $config->{digest_key},
                password_hashed => 1,
                authenticator   => sub { $config->{digest_password} }
            ) if $config->{auth};
            sub { $router->dispatch(shift); };
        }
    );
    $self->_controller(
        Bookmarks::Controller->new({
            dbname  => $self->config->{dbname},
        })
    );
}

sub call {
    my $self = shift;
    my $env = shift;

    # initialize the controller based on this request
    $self->_controller->request(Plack::Request->new($env));

    # dispatch to the app
    $self->_app->($env);
}

# module return
1;
