#!/usr/bin/perl -w
use strict;

use Encode;
use URI;
use CGI;
use YAML;
use DBI;
use Template;
use JSON;
use Bookmarks;

my $q = CGI->new;
my $template = Template->new;

my $method = $ENV{REQUEST_METHOD};

# bookmarklet to add a bookmark via the browser
# javascript:(function(){window.open("http://grim.ath.cx/~peter/bookmarks?uri="+document.location+"&title="+document.title,"edit_bookmark","width=800,height=250")})()

my $dbname = 'new.db';
my $dbh = DBI->connect("dbi:SQLite:dbname=$dbname", "", "", { RaiseError => 1 });

my $bookmarks = Bookmarks->new({
    dbh => $dbh,
});

=begin new style?

if ($ENV{PATH_INFO} =~ m{^/(\d+)(?:/(uri|title|tags))?\b}) {
    require Resource::Bookmark;
    my $resource = Resource::Bookmark->new({
        q => $q,
        id => $1,
        field => $2,
        bookmarks => $bookmarks,
    });
    $resource->$method();
}
exit;

=cut

my %resource = (
    GET => sub {
        my ($q, $dbh) = @_;
        if ($ENV{PATH_INFO} =~ m{^/(\d+)(?:/(uri|title|tags))?\b}) {
            my $id = $1;
            my $field = $2;
            my $bookmark = $bookmarks->get_bookmark({ id => $id });
            if ($bookmark) {
                if ($field) {
                    print $q->header(
                        -type    => 'text/plain',
                        -charset => 'UTF-8',
                    );
                    my $value = $bookmark->{$field};
                    print ref $value eq 'ARRAY' ? join(',', @{ $value }) : $value;
                } else {
                    $bookmark->{exists} = 1;
                    $bookmark->{created} = "Created " . localtime($bookmark->{ctime});
                    $bookmark->{created} .= '; Updated ' . localtime($bookmark->{mtime}) unless $bookmark->{ctime} == $bookmark->{mtime};
                    print $q->header(
                        -type    => 'text/html',
                        -charset => 'UTF-8',
                    );
                    $template->process(
                        'bookmark.tt',
                        $bookmark
                    );
                }
            } else {
                print $q->header(
                    -type    => 'text/html',
                    -charset => 'UTF-8',
                    -status  => 404,
                );
                print "Not Found";
            }
        } elsif (defined(my $uri = $q->param('uri'))) {
            my $bookmark = $bookmarks->get_bookmark({ uri => $uri });
            if ($bookmark) {
                #TODO: is there a better base URL to use?
                print $q->redirect($q->url . '/' . $bookmark->{id});
            } else {
                # bookmark was not found; show the form to create a new bookmark
                $bookmark->{uri} = $uri;
                $bookmark->{title} = $q->param('title');
                print $q->header(
                    -type    => 'text/html',
                    -charset => 'UTF-8',
                    -status  => 404,
                );
                $template->process(
                    'bookmark.tt',
                    $bookmark
                );
            }
        } else {
            # list all the bookmarks 
            my $format = $q->param('format') || 'html';
            my $tag = $q->param('tag');
            my @resources = $bookmarks->get_resources({ tag => $tag });
            my @all_tags = $bookmarks->get_tags({ selected => $tag });
            my @cotags = $bookmarks->get_cotags({ tag => $tag });

            if ($format eq 'json') {
                print $q->header(
                    -type    => 'application/json',
                    -charset => 'UTF-8',
                );
                print decode_utf8(
                    encode_json({
                        resources => \@resources,
                    })
                );
            } else {
                print $q->header(
                    -type    => 'text/html',
                    -charset => 'UTF-8',
                );

                # set the base URL, adding a trailing slash if needed
                my $base_url = $q->url;
                $base_url .= '/' if $base_url =~ m{/bookmarks$};

                $template->process(
                    'list.tt',
                    {
                        base_url     => $base_url,
                        selected_tag => $tag,
                        tags         => \@all_tags,
                        cotags       => \@cotags,
                        resources    => \@resources,
                    },
                );
            }
        }
    },
    POST => sub {
        #TODO: deal with changing URIs
        my ($q, $dbh) = @_;
        my $uri = $q->param('uri');
        my $title = $q->param('title');
        my @tags = split ' ', $q->param('tags');
        $bookmarks->add({
            uri   => $uri,
            title => $title,
            tags  => \@tags,
        });

        my $location = URI->new($q->url);
        $location->query_form(uri => $uri) if defined $q->url_param('uri');
        $location->fragment('updated');
        print $q->redirect($ENV{REQUEST_URI}); #$location);
    },
);

$resource{$method}->($q, $dbh);


