#!/bin/env perl

use strict;
use warnings;
use Sophie::Base;
use Sophie::Base::RpmsPath;
use Linux::Inotify2;
use POSIX ":sys_wait_h";
use Getopt::Long;

GetOptions(
    'bdelay=i' =>  \my $updated_inotify,
    'd|daemon'  => \my $daemon,
) or die "Wrong options";

$SIG{CHLD} = sub { wait };

my %modified_paths;
my $inotify = undef;
$updated_inotify ||= 300;

if ($daemon) {
    if (fork()) {
        exit(0);
    }
}

alarm($updated_inotify);
while (1) {
    local $SIG{ALRM} = sub {
        $inotify = undef;
        warn "reparse paths";
        alarm($updated_inotify);
    };
    if (update_base(keys %modified_paths)) {
        %modified_paths = ();
    }
    $inotify ||= inotify_path();
    $inotify->poll;
}

sub inotify_path {

    my $i = Linux::Inotify2->new;
    my $sophie = Sophie::Base->connect;
    
    foreach ($sophie->resultset('Paths')->get_column('path')->all) {
        $i->watch(
            $_,
            IN_DELETE | IN_MODIFY | IN_CREATE,
            sub {
                my $e = shift;
                warn $e->w->name;
                $modified_paths{$e->w->name} = 1;
                1;
            }
        )
    }

    $i;
}

sub update_base {
    my @path = @_;

    if (waitpid(-1, &WNOHANG) != -1) {
        warn "child still running";
        return;
    }
    warn "updating base";

    my @pkey;
    {
        my $sophie = Sophie::Base->connect or do {
            die "cannot read config file\n";
        };
        @pkey = $sophie->resultset('Paths')->search(
            path => [ @path ],
        )->get_column('d_path_key')->all;
        push(@pkey, $sophie->resultset('Paths')->search({
            updated => [ undef, 
                \[ " < now() - '6 hours'::interval"],
            ],
        })->get_column('d_path_key')->all);
        my %uniq = map { $_ => 1 } @pkey;
        @pkey = keys %uniq;
    }

    return 1 if (!@pkey);

    if (my $pid = fork()) {
    } else {


        my $NB_PAR = 2;
        my @split;
        my $div = @pkey / $NB_PAR;

        for (my $i = 0; $i < $NB_PAR - 1; $i++) {
            $split[$i] = [ splice(@pkey, 0, $div) ];
        }
        $split[$NB_PAR -1] = [ @pkey ];
        foreach my $job (@split) {
            @{$job || []} or next;

            if (fork()) {
            } else {

                foreach my $pathkey (@{ $job }) {
                    my @delta = Sophie::Base::RpmsPath->new($pathkey)
                        ->find_delta;
                    while (my @d = splice(@delta, 0, 25)) {
                        my $path = Sophie::Base::RpmsPath->new($pathkey);
                        $path->update_content(@d);
                        $path->db->disconnect;
                    }
                    Sophie::Base::RpmsPath->new($pathkey)->set_updated;
                }
                exit(0);
            }
        }
        1 while(waitpid(-1, 0) <= 0);
        exit(0);
    }
    return 1;
}

