# Type:        Input
# Category:    Task
# Description: Shows time spent for some period, project etc
# Author:      Andriy Lesyuk <s-andy@andriylesyuk.com>

new Orangutan::Context(
    response => sub {
        my ($context, $user, $message) = @_;

        my @result = ( );

        # Remove ending
        $message =~ s/\?*!*\.*$//;

        my $dayre =
            'Sun(?:day)?|Mon(?:day)?|Tue(?:sday)?|Wed(?:nesday)?|Thu(?:rsday)?|Fri(?:day)?|Sat(?:urday)?|yesterday|today';

        my @regexps = (
            'How much time (?:did )?(?:I|([^ ]+?)?) spen(?:d|t)',
            'Show (?:('.$dayre.') )?time(?: spent)? (?:of|by) ([^ ]+)',
            'Show (?:('.$dayre.') )?time(?: spent)?',
            'Show(?: (?:my|([^ ]+?)(?:\'s)?))? (?:('.$dayre.') )?time(?: spent)?'
        );

        # Check base query
        for (my $i = 0; $i < scalar @regexps; $i++) {
            if ($message =~ /^$regexps[$i] */i) {
                my ($day, $username) = (undef, undef);
                if ($i > 2) {
                    ($day, $username) = ($2, $1);
                } elsif ($i > 1) {
                    $day = $1;
                } elsif ($i > 0) {
                    ($day, $username) = ($1, $2);
                } else {
                    $username = $1;
                }
                if (defined($username)) {
                    my $id = $main::query->UserExists($username);
                    if ($id) {
                        push(@result, 1);
                        push(@result, $id);
                        if (defined($day)) {
                            ShowTasks_ParseDay($day, \@result);
                        }
                        $message =~ s/^$regexps[$i] *//i;
                        last;
                    }
                } else {
                    push(@result, 1);
                    push(@result, undef);
                    if (defined($day)) {
                        ShowTasks_ParseDay($day, \@result);
                    }
                    $message =~ s/^$regexps[$i] *//i;
                    last;
                }
            }
        }

        if (scalar @result > 0) {
            if (scalar @result == 2) {
                ShowTasks_ParsePeriod(\$message, \@result);
            }

            if (scalar @result == 2) {
                ShowTasks_DefaultPeriod(\$message, \@result);
            }

            ShowTasks_ParseFilter(\$message, \@result);

            if ($message !~ /^ *$/) {
                @result = ( );
            }
        }

        return @result;
    },
    handler => sub {
        my ($context, $manager, $item, $userid, $start, $end, $project, $issue, $activity) = @_;

        my $user;
        if (!defined($userid) || ($userid == $manager->GetUserID)) {
            $userid = $manager->GetUserID;
            $user = $manager;
        } elsif (!$manager->IsCreator && !$manager->IsManager) {
            $manager->SendMessage([
                'You have no permission to see this information...',
                'Sorry... Maybe next time...',
                "I can't do this!..",
                'Ask the user!'
            ]);
            return;
        } else {
            $user = $main::users->GetUserID($userid);
        }

        if (!defined($start) || !defined($end)) {
            $manager->SendMessage([
                'Something is wrong with your request... Please fix it!',
                'Hm... I guess you made some mistake...',
                'Cannot understand the request...'
            ]);
            return;
        }

        if (defined($issue)) {
            $manager->SendMessage([
                'Ignoring issue - it is not yet supported (and not sure if it is going to be)!',
                'I do not support issue in this request...'
            ]);
        }

        if (defined($activity) && (ref $activity ne 'HASH')) {
            my $format = Orangutan::Context::Random(
                'Activity %s does not exist in project %s...',
                "I can't find activity %s in project %s..."
            );
            $manager->SendMessage(sprintf($format, $activity, $project->{'name'}));
            return;
        }

        my $projectid = defined($project) ? $project->{'project_id'} : undef;
        my $activityid = defined($activity) ? $activity->{'id'} : undef;
        my %items = Orangutan::User::GetWorkHoursDetails(defined($user) ? $user : $userid,
            $start, $end, $projectid, $activityid);
        if (scalar keys %items > 0) {
            my $total = 0;
            foreach my $pid (keys %items) {
                my $ptotal = 0;
                foreach my $aid (keys %{$items{$pid}->{'activities'}}) {
                    $ptotal += $items{$pid}->{'activities'}->{$aid}->{'duration'};
                    if (!defined($items{$pid}->{'activities'}->{$aid}->{'name'})) {
                        delete($items{$pid}->{'activities'}->{$aid});
                    }
                }
                $items{$pid}->{'duration'} = $ptotal;
                $total += $ptotal;
            }
            my $message;
            if ($userid == $manager->GetUserID) {
                $message = Orangutan::Context::Random(
                    'Total time is',
                    'You spent'
                ).' ';
            } else {
                $message = Orangutan::Context::Random(
                    'Total time is',
                    'User spent'
                ).' ';
            }
            $message .= sprintf('%d:%02d', int($total / 3600), int(($total % 3600) / 60));
            if (defined($user)) {
                my $hours = $user->GetWorkTimeHours;
                if ($hours) {
                    my $days = scalar $user->GetWorkDays($start->WorkDayStart, $end->WorkDayStart);
                    if ($days) {
                        my $required = $days * ($hours * 3600);
                        $message .= ' (';
                        $message .= sprintf('%.02f%%', ($total * 100) / $required);
                        $message .= ' '.Orangutan::Context::Random(
                            'of what it should be',
                            'of required time'
                        );
                        if ($required > $total) {
                            $message .= ' (+';
                            $message .= sprintf('%d:%02d',
                                int(($required - $total) / 3600), int((($required - $total) % 3600) / 60));
                            $message .= ')';
                        }
                        $message .= ')';
                    }
                }
            }
            if (scalar keys %items == 1) {
                my $pid = (keys %items)[0];
                $message .= ' on '.$items{$pid}->{'name'};
                $message .= ' (';
                my @asort = sort {
                    $items{$pid}->{'activities'}->{$a}->{'name'} cmp $items{$pid}->{'activities'}->{$b}->{'name'}
                } keys %{$items{$pid}->{'activities'}};
                if ((scalar @asort == 1) &&
                    ($items{$pid}->{'activities'}->{$asort[0]}->{'duration'} == $items{$pid}->{'duration'})) {
                    $message .= $items{$pid}->{'activities'}->{$asort[0]}->{'name'};
                } else {
                    for (my $j = 0; $j < scalar @asort; $j++) {
                        if ($j > 0) {
                            if ($j == $#asort) {
                                $message .= ' and ';
                            } else {
                                $message .= ', ';
                            }
                        }
                        $message .= $items{$pid}->{'activities'}->{$asort[$j]}->{'name'}.' - ';
                        $message .= sprintf('%d:%02d ',
                            int($items{$pid}->{'activities'}->{$asort[$j]}->{'duration'} / 3600),
                            int(($items{$pid}->{'activities'}->{$asort[$j]}->{'duration'} % 3600) / 60));
                        $message .= sprintf('(%.02f%%)',
                            ($items{$pid}->{'activities'}->{$asort[$j]}->{'duration'} * 100) / $items{$pid}->{'duration'});
                    }
                }
                $message .= ')';
            }
            $message .= ".\n";
            if (scalar keys %items > 1) {
                $message .= ' ';
                my @psort = sort { $items{$a}->{'name'} cmp $items{$b}->{'name'} } keys %items;
                for (my $i = 0; $i < scalar @psort; $i++) {
                    if ($i == $#psort) {
                        $message .= ' and ';
                    } elsif ($i != 0) {
                        $message .= ', ';
                    }
                    $message .= sprintf('%d:%02d ',
                        int($items{$psort[$i]}->{'duration'} / 3600), int(($items{$psort[$i]}->{'duration'} % 3600) / 60));
                    $message .= sprintf('(%.02f%%)', ($items{$psort[$i]}->{'duration'} * 100) / $total);
                    $message .= ' on '.$items{$psort[$i]}->{'name'};
                    $message .= ' (';
                    my @asort = sort {
                        $items{$psort[$i]}->{'activities'}->{$a}->{'name'} cmp $items{$psort[$i]}->{'activities'}->{$b}->{'name'}
                    } keys %{$items{$psort[$i]}->{'activities'}};
                    if ((scalar @asort == 1) &&
                        ($items{$psort[$i]}->{'activities'}->{$asort[0]}->{'duration'} == $items{$psort[$i]}->{'duration'})) {
                        $message .= $items{$psort[$i]}->{'activities'}->{$asort[0]}->{'name'};
                    } else {
                        for (my $j = 0; $j < scalar @asort; $j++) {
                            if ($j > 0) {
                                if ($j == $#asort) {
                                    $message .= ' and ';
                                } else {
                                    $message .= ', ';
                                }
                            }
                            $message .= $items{$psort[$i]}->{'activities'}->{$asort[$j]}->{'name'}.' - ';
                            $message .= sprintf('%d:%02d ',
                                int($items{$psort[$i]}->{'activities'}->{$asort[$j]}->{'duration'} / 3600),
                                int(($items{$psort[$i]}->{'activities'}->{$asort[$j]}->{'duration'} % 3600) / 60));
                            $message .= sprintf('(%.02f%%)',
                                ($items{$psort[$i]}->{'activities'}->{$asort[$j]}->{'duration'} * 100) /
                                $items{$psort[$i]}->{'duration'});
                        }
                    }
                    $message .= ')';
                }
                $message .= '.';
            }
            $manager->SendMessage($message);
        } else {
            $manager->SendMessage([
                'You did not work at that time...',
                'There were no tasks...'
            ]);
        }

    },
    help => {
        title    => 'How can I check how much time did I spend?',
        question => [
            '^(?:(?:How )?(?:(?:can|do) I |to )(?:check|see) )?how much (?:time|hours) '.
            '(?:did )?I spen[td](?: (?:during|for|at) some period)?\?*!*\.*$',
            '^(?:How )?(?:(?:can|do) I |to )(?:check|see) (?:my )?(?:work(?:ing)? )?(?:time|hours)(?: spent)?'.
            '(?: (?:during|for|at) some period)?\?*!*\.*$'
        ],
        answer   => "Orangutan can show you a very simple report on the time you spent. ".
                    "It can show time for today, yesterday, current week, last month or any other period.\n".
                    "Sample queries:\n".
                    " o Show time from 1st March to 10th March\n".
                    " o How much time did I spend last month?\n".
                    " o How much time did I spend in August?\n".
                    " o Show time spent on last week\n".
                    " o Show time spent on Monday\n".
                    " o Show time for yesterday\n".
                    "You can optionally specify project or activity:\n".
                    " o How much time did I spend (Meetings)?\n".
                    " o Show time on Orangutan\n".
                    "The report can be shown only for days (you can't specify hours)...",
        weight   => 710
    },
    weight => 90
);
# kate: syntax perl