#!/usr/bin/perl

use strict;
use warnings;

package FileApp;
use Template;
use File::Slurp;
use vars qw{$AUTOLOAD};

sub new {
	my ($class, @params) = @_;
	bless {
		sessiondir => '.sessions',
		userdir => 'users',
		templatedir => 'templates',
		@params
	}, $class;
}

# a no-op for file based app
sub commit {
	return;
}

sub newcgi {
	my ($class, $q, @params) = @_;
	my $app = $class->new(@params);
	my $sid = $q->cookie('SID');
	if ($sid) {
		eval {
			$app->{user} = $app->checksession($sid);
		};
		if ($@ and $@ eq 'expired') {
			warn "session $sid expired";
			unlink $app->sessionfile($sid);
			return $app;
		}
		if ($@) {
			warn "checksession: $@";
		}
		$app->{msg} = $@;
		$app->{SID} = $sid;
	}
	return $app;
}

sub newsession {
	my ($app, $info) = @_;
	my $uuid = `uuidgen`;
	chomp $uuid;
	$uuid =~ s/-//g;
	mkdir $app->{sessiondir};
	write_file("$app->{sessiondir}/$uuid", $info);
	return $uuid;
}

sub info {
	my ($app) = @_;
	my $user = $app->user;
	opendir(my $dh, $app->homedir . '/images');
	my @imagefiles = grep { !/^\./ } readdir $dh;
	close $dh;

	return {
		images => \@imagefiles,
	};

}

sub readsession {
	my ($app, $sid) = @_;
	return read_file($app->{sessiondir} . "/$sid");
}

sub renewsession {
	my ($app, $sid) = @_;
	my $time = time;
	utime $time, $time, $app->{sessiondir} . "/$sid";
}

sub sessionfile {
	my ($app, $sid) = @_;
	$app->{sessiondir} . "/$sid";
}

sub checksession {
	my ($app, $sid) = @_;
	my $user = $app->readsession($sid);
	if (!$user) {
		die "no session";
	}
	my $mtime = (stat $app->sessionfile($sid))[9];
	if (time > $mtime + 15 * 60) {
		die "expired";
	}

	$app->renewsession($sid);
	return $user;
}

sub login {
	my ($app, $username, $password) = @_;
	my $pwhash = read_file($app->{userdir} . "/$username/.password");
	if (!defined $pwhash) {
		die "no password";
	}
	if ($pwhash eq $password) {
		return $app->newsession($username);
	}
	die 'bad password';
}

sub setpassword {
	my ($app, $username, $password) = @_;
	write_file($app->{userdir} . "/$username/.password", $password);
}

sub create_user {
	my ($app, $username, $password) = @_;
	unless (-d $app->{userdir} ) {
		mkdir "$app->{userdir}" or die "$>:$) can't make $app->{userdir}: $!";
	}
	mkdir "$app->{userdir}/$username" or die "$>:$) can't make $app->{userdir}/$username: $!";
	$app->setpassword($username, $password);
}

sub t {
	my ($app) = @_;
	if (!$app->{t}) {
		$app->{t} = Template->new({INCLUDE_PATH=>$app->{templatedir}});
	}
	return $app->{t};
}

# lets auto-create accessors
sub AUTOLOAD {
	my ($app, @args) = @_;
	my $field = $AUTOLOAD;
	if (@args) {
		$app->{$AUTOLOAD} = $_[0];
		return $app;
	}
	return $app->{$AUTOLOAD};

# 	*$field = sub {
# 		my ($a, @arg) = @_;
# 		if ($arg[0]) {
# 			$a->{$field} = $arg[0];
# 			return $a;
# 		}
# 		return $a->{$field};
# 	}

}

1;
