# -*- mode: perl; coding: utf-8 -*-
# Keitairc::View
#
# Copyright (c) 2008 Jun Morimoto <morimoto@mrmt.net>
# This program is covered by the GNU General Public License 2

package Keitairc::View;
use HTML::Template;
use HTTP::Response;
use HTTP::Status;
use HTTP::Date;
use Keitairc::Config;
use Keitairc::ClientInfo;
use strict;
use warnings;

################################################################
sub new{
	my $proto = shift;
	my $cf = shift;
	my $ci = shift;
	my $session_id = shift;
	my $me = {};
	$me->{Config} = $cf;
	$me->{ClientInfo} = $ci;
	if(defined $session_id){
		$me->{session_id} = $session_id;
	}
        bless $me;
}

################################################################
sub redirect{
	my $me = shift;
	my $path = shift;

	if($me->{Config}->web_root() ne '/'){
		# Softbank
		$path =~ s|^/||;
		$path = sprintf('%s%s', $me->{Config}->web_root(), $path);
	}

	$::log->log_debug("path [$path]");

	my $response = HTTP::Response->new(302);
	$response->push_header('Location', $path);
	$response;
}

################################################################
sub template_path{
	my $me = shift;
	my $template = shift;
	for my $template_dir (split(':', $me->{Config}->template_dir())){
		if(-r "$template_dir/$template"){
			return "$template_dir/$template";
		}
	}
}

################################################################
sub public_path{
	my $me = shift;
	my $file = shift;
	for my $public_dir (split(':', $me->{Config}->public_dir())){
		if(-r "$public_dir/$file"){
			return "$public_dir/$file";
		}
	}
}

################################################################
sub template{
	my $me = shift;
	my $template = shift;
	my $vars = shift;

	my $p = {};
	$p->{root} = $me->{Config}->web_root();
	$p->{title} = $me->{Config}->web_title();
	$p->{version} = $me->{Config}->version();
	$p->{common_header} = $me->{Config}->common_header();
	$p->{extra_header} = $me->{Config}->extra_header();
	$p->{content_charset} = $me->{Config}->content_charset();

	if($me->{ClientInfo}->is_mobile){
		$p->{fontsize} = $me->{Config}->mobile_fontsize();
	}else{
		$p->{fontsize} = $me->{Config}->fontsize();
	}
	$p->{target} = $me->{Config}->url_target();
	$p->{redirect} = $me->{Config}->url_redirect();
	$p->{timestamp} = timestamp();
	$p->{stamp} = time;

	$p->{is_webkit} = $me->{ClientInfo}->is_webkit();
	$p->{is_docomo} = $me->{ClientInfo}->is_docomo();
	$p->{is_ezweb} = $me->{ClientInfo}->is_ezweb();
	$p->{is_softbank} = $me->{ClientInfo}->is_softbank();
	$p->{is_emobile} = $me->{ClientInfo}->is_emobile();
	$p->{is_mobile} = $me->{ClientInfo}->is_mobile();

	map {
		$p->{"plugin_$_"} = 1;
	} $::pl->list_plugins();

	my $arch = 'default';
	if($me->{ClientInfo}->is_webkit()){
		if($me->{Config}->webkit_newui()) {
			$arch = 'webkit';
		} else {
			$arch = 'webkit-legacy';
		}
	}

	if (my $filename = $me->template_path("$arch/$template")) {
		my $t = new HTML::Template(
			filename => $filename,
			die_on_bad_params => 0,
			filter => sub {
				my $text_ref = shift;
				$$text_ref = Encode::decode('utf8', $$text_ref);
			},
			cache => 1);
		$t->param($p);

		if(defined $vars){
			$t->param($vars);
		}

		$t->output();
	}
}

################################################################
sub public{
	my ($me, $request, $file) = @_;

	my $mime_types = {
		html => 'text/html',
		css => 'text/css',
		gif => 'image/gif',
		png => 'image/png',
		jpg => 'image/jpg',
		txt => 'text/plain',
		js => 'application/javascript',
	};

	my ($ext) = ($file =~ /\.(.*)$/);
	my $mime_type = $mime_types->{$ext} || 'text/plain';

	my $mtime = (stat($me->public_path($file)))[9] || 0;
	my $mod;
	if ($mod = $request->header('If-Modified-Since')){
		my $str_mod = str2time($mod);
		if($str_mod
		   && $str_mod <= $mtime) {
			my $response = HTTP::Response->new(304);
			$response->push_header('Content-type', $mime_type);
			$response->push_header('Last-Modified', time2str($mtime));
			return $response;
		}
	}

	if(open(my $fh, '<', $me->public_path($file))){
		local $/;
		undef $/;
		my $buf = join('', <$fh>);
		close($fh);

		my $response = HTTP::Response->new(200);
		$response->push_header('Content-type', $mime_type);
		$response->push_header('Last-Modified', time2str($mtime));
		#$response->expires(time + $me->{Config}->cache_expire()) if (!$me->{Config}->debug() && $me->{Config}->cache_expire());
		$response->content($buf);
		return $response;
	}

	# not found
	my $response = HTTP::Response->new(404);
	$response->push_header('Content-type', 'text/html; charset=' . $me->{Config}->content_charset());
	$response->content(Encode::encode($me->{Config}->web_charset(),
					  $me->template('error.html', { action => $file,
									_http_status_code => 404,
									_http_status_message => status_message(404)})));
	return $response;
}

################################################################
sub render{
	my $me = shift;
	my $template = shift;
	my $vars = shift || {};
	$vars->{_http_status_code} ||= 200;
	my $response = HTTP::Response->new($vars->{_http_status_code});
	$vars->{content_type} |= 'text/html; charset=' . $me->{Config}->content_charset();
	$response->push_header('Content-type', $vars->{content_type});
	$response->content(Encode::encode($me->{Config}->web_charset(), $me->template($template, $vars)));
	$response;
}

################################################################
sub timestamp{
	my ($sec, $min, $hour, $day, $mon, $year) = localtime(time);
	sprintf('%d/%d/%d %02d:%02d:%02d',
		$year+1900, $mon+1, $day, $hour, $min, $sec);
}

1;
