The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
#!/usr/bin/perl

use strict;
use warnings;
use utf8;
use File::Path qw/mkpath/;
use Getopt::Long;
use Pod::Usage;
use Text::Xslate;
use Data::Section::Simple qw(get_data_section);
use File::ShareDir qw/dist_file/;
use File::Copy;
use MIME::Base64;
use Encode;
use File::Basename;

require Kossy;

GetOptions(
    'help' => \my $help,
) or pod2usage(0);
pod2usage(1) if $help;

sub _mkpath {
    my $d = shift;
    print "mkdir $d\n";
    mkpath $d;
}

my $module = shift @ARGV or pod2usage(0);
my @pkg  = split /::/, $module;
my $dist = join "-", @pkg;
my $path = join "/", @pkg;

my $tx = Text::Xslate->new(syntax => 'TTerse');

mkdir $dist or die $!;
chdir $dist or die $!;
_mkpath "lib/$path";
_mkpath "views";
_mkpath "t";

my @share_files = qw!
public/css/bootstrap-responsive.min.css
public/css/bootstrap.min.css
public/favicon.ico
public/img/glyphicons-halflings-white.png
public/img/glyphicons-halflings.png
public/js/bootstrap.min.js
public/js/jquery.min.js
!;

foreach my $file ( @share_files ) {
    print "writing $file\n";
    _mkpath( dirname($file) ) if ! -d dirname($file);
    copy dist_file('Kossy',$file), $file;
}

my $files = get_data_section();
my $args = {
    module => $module,
    path => $path,
    dist => $dist,
    myver => $Kossy::VERSION,
};
foreach my $fkey ( keys %{$files} ) {
    my $path = $tx->render_string($fkey, $args);
    my $content = $tx->render_string($files->{$fkey}, $args);
    $content = encode_utf8($content);
    print "writing $path\n";
    open(my $fh, '>', $path);
    print $fh $content
}

=head1 SYNOPSIS

    % kossy-setup MyApp

=cut

1;
__DATA__
@@ lib/[% path %].pm
package [% module %];

use strict;
use warnings;
use utf8;

our $VERSION = 0.01;

1;

@@ lib/[% path %]/Web.pm
package [% module %]::Web;

use strict;
use warnings;
use utf8;
use Kossy;

filter 'set_title' => sub {
    my $app = shift;
    sub {
        my ( $self, $c )  = @_;
        $c->stash->{site_name} = __PACKAGE__;
        $app->($self,$c);
    }
};

get '/' => [qw/set_title/] => sub {
    my ( $self, $c )  = @_;
    $c->render('index.tx', { greeting => "Hello" });
};

get '/json' => sub {
    my ( $self, $c )  = @_;
    my $result = $c->req->validator([
        'q' => {
            default => 'Hello',
            rule => [
                [['CHOICE',qw/Hello Bye/],'Hello or Bye']
            ],
        }
    ]);
    $c->render_json({ greeting => $result->valid->get('q') });
};

1;

@@ views/base.tx
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html" charset="utf-8">
<title>[% module %]</title>
<link rel="shortcut icon" href="<: $c.req.uri_for('/favicon.ico') :>" type="image/vnd.microsoft.icon" />
<link rel="stylesheet" href="<: $c.req.uri_for('/css/bootstrap.min.css') :>">
<style>
body {
  padding-top: 60px;
}
</style>
<link rel="stylesheet" href="<: $c.req.uri_for('/css/bootstrap-responsive.min.css') :>">
</head>
<body>

<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a class="btn btn-navbar" data-toggle="collapse" data-target=".nav-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</a>
<a class="brand" href="<: $c.req.uri_for('/') :>">[% module %]</a>
<div class="nav-collapse">
<ul class="nav">
<li class="active"><a href="<: $c.req.uri_for('/') :>">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
</div> <!--/.nav-collapse -->
</div>
</div>
</div>

<div class="container">

: block content -> { }

</div> <!-- /container -->

<script type="text/javascript" src="<: $c.req.uri_for('/js/jquery.min.js') :>"></script>
<script type="text/javascript" src="<: $c.req.uri_for('/js/bootstrap.min.js') :>"></script>
</body>
</html>


@@ views/index.tx
: cascade base
: around content -> {
<h1><: $greeting :> <: $c.stash.site_name :></h1>
<p>Use this document as a way to quick start any new project.<br> All you get is this message and a barebones HTML document.</p>
: }

@@ app.psgi
use FindBin;
use lib "$FindBin::Bin/extlib/lib/perl5";
use lib "$FindBin::Bin/lib";
use File::Basename;
use Plack::Builder;
use [% module %]::Web;

my $root_dir = File::Basename::dirname(__FILE__);

my $app = [% module %]::Web->psgi($root_dir);
builder {
    enable 'ReverseProxy';
    enable 'Static',
        path => qr!^/(?:(?:css|js|img)/|favicon\.ico$)!,
        root => $root_dir . '/public';
    $app;
};

@@ Makefile.PL
use ExtUtils::MakeMaker;

WriteMakefile(
    NAME          => '[% module  %]',
    VERSION_FROM  => 'lib/[% path %].pm',
    PREREQ_PM     => {
        'Kossy' =>  '[% myver %]',
    },
    MIN_PERL_VERSION => '5.008001'
);

@@ t/00_compile.t
use strict;
use warnings;
use Test::More;

use_ok $_ for qw(
    [% module %]
    [% module %]::Web
);

done_testing;