package Web::App::Controller;

use strict;
use warnings;

use URI;
use Web::Canvas;

sub new {
	my ($class, $app, $page) = @_;
	my $self = bless {
		app => $app,
		page => $page,
		canvas => Web::Canvas->new($app),
		params => {},
	}, $class;
	
	return $self;
}

sub app { $_[0]->{app} }
sub page { $_[0]->{page} }
sub cgi { $_[0]->page->cgi }
sub domain { $_[0]->app->domain }
sub canvas { $_[0]->{canvas} }
sub params { wantarray ? values %{$_[0]->{params}} : $_[0]->{params} }
sub param { $_[0]->params->{$_[1]} }

sub set_params { $_[0]->{params} = $_[1]; $_[0] }

sub reload {
	my ($self) = @_;
	
	print $self->cgi->redirect($self->cgi->url.$self->cgi->path_info);
	die;
}

sub reload_with_errors {
	my ($self, @errors) = @_;
	my $uri = URI->new($self->cgi->url.$self->cgi->path_info);
	
	$uri->query_form(%{$self->params}, errors => \@errors);
	
	print $self->cgi->redirect($uri->as_string);
	die;
}

sub fail {
	my ($self, %error_fields) = @_;
	my %errors;
	
	for my $field (keys %error_fields) {
		my $error = $error_fields{$field};
		
		$errors{$field} = 1;
		
		if (defined $error) {
			$errors{"$field\_$error"} = 1;
		}
	}
	
	$self->reload_with_errors(keys %errors);
}

sub show {
	my ($self, $name) = @_;

	print $self->cgi->redirect($self->app->url($name));
	die;
}

sub validate_params {
	my ($self, @stuff) = @_;
	my @return;
	my %return;
	my @errors;
	
	# Might need to preserve order, so no hash for @stuff
	while (@stuff) {
		my $name = shift @stuff;
		my $pattern = shift @stuff;
		my $value = $self->params->{$name};
		
		if (defined $value && $value =~ $pattern) {
			push @return, $value;
			$return{$name} = $value;
			
			next;
		}
		
		push @errors, $name;
	}
	
	if (@errors) {
		$self->fail(map { $_ => 'not_valid' } @errors);
	}
	
	return wantarray ? @return : \%return;
}

1;
