#!/usr/local/bin/tclsh
#
# arpt - artts reporter
#
# Copyright 1994, 1995 Paul E Coad
# The author disclaims all warranties with regard to this software, including
# all implied warranties of merchantability and fitness.  In no event
# shall the author be liable for any special, indirect or consequential
# damages or any damages whatsoever resulting from loss of use, data or
# profits, whether in an action of contract, negligence or other
# tortuous action, arising out of or in connection with the use or
# performance of this software.
#
# This package is being released under the terms of Larry Wall's
# "Artistic license".

# arpt - 1.0
# This script provides a simple reporting facility for use with .arttsdb
# files. 

set arpt_version 1.0
set arpt(seperator) "================================"
set arpt(tot_line) "--------------"
set arpt(tot_format) "%02i:%02i:%02i"

#---------------------------------------------------------------
# Build a list containing all of the data from the database file
# arguments: 	file_name	the name of the database file
# returns:	task_list	a list of tasks
#				task seconds start_list stop_list
#---------------------------------------------------------------
proc build_task_list {file_name} {
    set task_list ""
    set file [open $file_name r]
    while {[eof $file] != 1} {
	set x [gets $file]
	set y [split $x]

	# The first 6 fields are the start time
	set start [lrange $y 0 5]
	# The second 6 fields are the stop time
	set stop [lrange $y 6 11]
	# The next field is the elapsed time
	set time [lindex $y 12]
	# The remaining fields are the task name
	set task [join [lrange $y 13 end] ]

	lappend tlist [list $task $time $start $stop]
	
    }
    return $tlist
}

#---------------------------------------------------------------
# Convenience procs 
proc get_task {task_line} { return [lindex $task_line 0] }
proc get_seconds {task_line} { return [lindex $task_line 1] }
proc get_start {task_line} { return [lindex $task_line 2] }
proc get_stop {task_line} { return [lindex $task_line 3] }
proc get_ymd {time} { return [lrange $time 0 2] }
proc get_year {time} { return [lindex $time 0] }
proc get_month {time} { return [lindex $time 1] }
proc get_day {time} { return [lindex $time 2] }
proc get_hms {time} { return [lrange $time 3 5] }

#---------------------------------------------------------------
# Print the total times for each task for each day using a supplied proc
# arguments:	tlist		task_list
#		print_proc	proc to call to print the results
# returns:	nothing
#---------------------------------------------------------------
proc print_dalies {tlist print_proc} {
    global arpt

    set day 0 
    set task_list ""
    set dlist ""
    set first 0
    set last 0

    foreach i $tlist {
	set prev_day $day
	set day [get_day [get_start $i]]
	if {$day != $prev_day && $prev_day != 0} {
	    # The day changed
	    $print_proc [lrange $tlist [expr ($first - 1)] [expr $last-1]]
	    incr last
	    set first $last
	} else {
	    incr last
	} 
    }
}

#---------------------------------------------------------------
# total_today - get todays tasks from a task_list
# arguments:	tlist	task_list
# returns:	list	task_list with todays tasks only
#---------------------------------------------------------------
proc total_today {tlist} {
    global arpt

    set day 0 
    set task_list ""
    set dlist ""
    set first 0
    set last 0
    set out_list ""
    set today [get_ymd [get_date_time]]
    set this_day [get_ymd [get_start [lindex $tlist 0]]

    foreach i $tlist {
	set prev_day $day
	set day [get_day [get_start $i]]
	if {$day != $prev_day && $prev_day != 0} {
	    # The day changed
	    if {$this_day == $today} {
		set out_list [lrange $tlist [expr ($first - 1)] $last]
	    }
	    incr last
	    set first $last
	} else {
	    incr last
	} 
	set this_day [get_ymd [get_start $i]]
    }
    return $out_list
}

#---------------------------------------------------------------
# print_it - print the time for each task and total for all tasks
# arguments: 	l	task_list
# returns:	nothing
#---------------------------------------------------------------
# Printing proc
proc print_it {l} {
    global arpt

    set line [lindex $l 0]
    set s [get_start $line]
    puts $arpt(seperator)
    puts "Date: [format "\t%s/%s/%s" [get_month $s] [get_day $s] [get_year $s]]"
    set total [total_by_task $l]
    set total_time 0
    foreach i $total {
	set seconds [lindex $i 1]
	set task [lindex $i 0]
	puts "[format_time $seconds] $task"
	if {[lsearch $arpt(exclude) $task] == -1} {
	    incr total_time $seconds
	}
    }
    puts $arpt(tot_line)
    puts "[format_time $total_time] Total"
    puts $arpt(seperator)
}

#---------------------------------------------------------------
# format_time - put the time in seconds in a pretty format
#
# arguments:    seconds (int)
# returns:      formatted string hh:mm:ss
#---------------------------------------------------------------
proc format_time {seconds} {
    global arpt

    set hours [expr (($seconds / 3600) % 3600)]
    set minutes [expr (($seconds - ($hours * 3600)) / 60) % 60]
    set secs [expr ($seconds - ($hours * 3600) - ($minutes * 60))]
    return [format $arpt(tot_format) $hours $minutes $secs]
}

#---------------------------------------------------------------
# Get the totals for each task from a tasklist
# arguments:	l	task_list
# returns:	list	list of lists with each element: task seconds
#---------------------------------------------------------------
proc total_by_task {l} {
    foreach i $l {
	set task [get_task $i]
	if {[info exists total($task)]} {
	   set total($task) [expr [get_seconds $i] + $total($task)]
	} else {
	    if {$task != ""} {
		set total($task) [get_seconds $i]
	    }
	}
    }

    foreach j [array names total] {
	if {$j != ""} {
	    lappend tot_list [list $j $total($j)]
	}
    }
    return $tot_list
}


#---------------------------------------------------------------
# Print the total times for each task for each day using a supplied proc
proc task_totals {tlist print_proc} {
    global arpt

    $print_proc $tlist
}

#---------------------------------------------------------------
# print_totals - print the total time for each task in the task list
# arguments:	l	task_list
# returns:	nothing
#---------------------------------------------------------------
proc print_totals {l} {
    global arpt

    set line [lindex $l 0]
    set start [get_start $line]
    set len [expr [llength $l] - 2 ]
    set line [lindex $l $len]
    if {$line == "{} {} {} {}"} {
	set line [lindex $l [expr $len -1]]
    }
    set stop [get_start $line]
    puts $arpt(seperator)
    puts "Span: [format "\t%s/%s/%s - %s/%s/%s" \
		[get_month $start] [get_day $start] [get_year $start] \
		[get_month $stop] [get_day $stop] [get_year $stop]]"
    set total [total_by_task $l]
    set total_time 0
    foreach i $total {
	set seconds [lindex $i 1]
	set task [lindex $i 0]
	puts "[format_time $seconds] $task"
	if {[lsearch $arpt(exclude) $task] == -1} {
	    incr total_time $seconds
	}
    }
    puts $arpt(tot_line)
    puts "[format_time $total_time] Total"
    puts $arpt(seperator)
}

#---------------------------------------------------------------
# get_date_time - gets the current date and time
#
# args: none
# returns: list - (two digits each) year month day hour minute second
#---------------------------------------------------------------
proc get_date_time {} {
    catch {exec date +%y:%m:%d:%H:%M:%S} date_time_value
    scan $date_time_value "%d:%d:%d:%d:%d:%d" year month day hours mins secs
    return [list $year $month $day $hours $mins $secs]
}

#==========================
## Start of main processing
#==========================
set file_name "~/.arttsdb"

set show_usage 1
set do_today 0
set do_totals 0
set do_dalies 0
for {set i 0} {$i < $argc} { incr i 1} {
    set flag [string tolower [lindex $argv $i]]
    switch -exact -- $flag {
	{-f} {incr i; if {$i < $argc} {set file_name [lindex $argv $i]}}
	{-t} {set do_today 1; set show_usage 0}
	{-s} {set do_totals 1; set show_usage 0}
	{-d} {set do_dalies 1; set show_usage 0}
	{-h} {puts "usage: -t todays totals, -s sum totals, -d dalies, \				   -h help, -l long help"}
	{-l} {puts "-h    displays a short usage message."
	      puts "-l    displays a long usage message."
	      puts "-d    displays a report of daily totals (each task is \
	      		  totaled for each day.)"
	      puts "-s    displays a report of all totals (all tasks are \
			  totaled over the span "
	      puts "      of days in the .arttsdb file."
	      puts "-t    displays a report of time spent on tasks today."
	     }
	{default} {puts "unknown option: $flag"}
    }
}

source ~/.arttsrc
set tl [build_task_list $file_name]

puts "* arpt $arpt_version *"

if {$do_dalies} {
    print_dalies $tl print_it
}
if {$do_totals} {
    task_totals $tl print_totals
}

if {$do_today} {
    set today [total_today $tl]
    print_dalies $today print_it
}

if {$show_usage} {
    puts "arpt usage: -t todays totals, -s sum totals, -d dalies, \
	  -h help, -l long help"
}
