package CMTD::Helpers;

use strict;
use warnings;
use utf8;

use Mojo::Base 'Mojolicious::Plugin';
use Mojo::Util qw(b64_encode md5_sum);
use Mojo::URL;

sub register {
  my ($self, $app) = @_;

  $app->helper(referrer => sub {
    my ($c) = @_;
    my $url = $c->req->headers->referrer ||
              $c->req->param('url');
    return unless $url;
    my $u = Mojo::URL->new($url);
    my $site = $u->host;
    my $path = $u->path;
    $path =~ s{^/+}{}o;
    $path =~ s{/+$}{}o;
    $path =~ y{/.}{-}s;
    $path =~ s<\.[a-z0-9]{2,4}$><>io;
    my $md5 = md5_sum($path);

    return {site => $site, hash => $md5, path => $path};
  });

  $app->helper(maintenance => sub {
    my ($c) = @_;
    eval {
      my $table = 'captcha';
      my $tries = $c->app->config->{captcha}->{tries};
      my $limit = $c->app->config->{captcha}->{limit};

      $c->app->db->delete($table, {tries => {'>=' => $tries}});
      my $count = $c->app->db->select($table, 'count(id)')->list;
      if ($count < $limit) {
        $c->app->db->begin;
        foreach my $n ($count + 1 .. $limit) {
          $c->app->log->info("generating captcha's: $n of $limit");
          my ($code, $data) = $c->app->captcha->create;
          next unless $code and $data;
          my $b64 = 'data:image/jpeg;base64,' . b64_encode($data, '');
          $c->app->db->insert($table, { code => $code, data => $b64 });
        }
        $c->app->db->commit;
      } 1;
    } or do {
      chomp $@;
      $c->app->log->error($@);
    };
  });

  $app->helper(client_reply => sub {
    my ($c, $code, $msg) = @_;
    $c->res->code($code);
    $c->render(text => "$msg\n");
    $c->rendered;
    return;
  });

  $app->helper(site_by_name => sub {
    my ($c, $site) = @_;
    return $c->app->db->select('sites', '*', {site => $site})->hash;
  });

  $app->helper(pid_by_hash => sub {
    my ($c, $sid, $hash) = @_;
    return $c->app->db->select('pages', 'id', {sid => $sid, hash => $hash})->list;
  });
  $app->helper(comments_by_pid => sub {
    my ($c, $pid) = @_;
    return $c->app->db->select('comments', '*', {pid => $pid}, 'seq')->hashes;
  });
  $app->helper(captcha_by_id => sub {
    my ($c, $cid) = @_;
    return $c->app->db->select('captcha', '*', {cid => $cid})->hash;
  });
  $app->helper(captcha_solve => sub {
    my ($c, $id, $input) = @_;
    my $cap = $c->app->db->select('captcha', '*', {cid => $id})->hash;
    return "no captcha with this id"
      unless $cap and ref($cap) eq 'HASH';
    if ($cap->{code} ne $input) {
      if ($cap->{tries} + 1 >= $app->config->{tries}) {
        $app->db->delete('captcha', {id => $cap->{id}});
      } else {
        $app->db->update('captcha', \'tries = tries + 1', {id => $cap->{id}});
      }
      return "captcha code mismatch";
    }
  });
  $app->helper(get_captcha => sub {
    my ($c) = @_;
    my $table = 'captcha';
    my @sort = qw(shown tries);
    $app->db->begin;
    my ($cid, $data) = $app->db->select($table, ['id', 'data'], undef, \@sort)->list;
    $app->db->update($table, {shown => time()}, {id => $cid});
    $app->db->commit;
    return ($cid, $data);
  });
  $app->helper(add_page => sub {
    my ($c, $sid, $page) = @_;
    $c->app->db->insert('pages', {
      sid  => $sid,
      hash => $page->{hash},
      path => $page->{path},
    });
  });
  $app->helper(add_comment => sub {
    my ($c, $pid, $cm) = @_;
    my $table = 'comments';
    $c->app->db->begin;
    my $seq = $c->app->db->select($table, 'max(seq)', {pid => $pid})->list;
    $c->app->db->insert($table, {
      pid  => $pid,
      seq  => $seq,
      date => time(),
      name  => $cm->{name},
      reply => $cm->{reply},
      email => $cm->{email},
      text  => b64_encode($cm->{text}),
    });
    $c->app->db->commit;
  });
}

1;