#!/bin/bash
#
# This file is part of the battery-stats package.
# Copyright (C) 2015 F Zenke <fzenke@stanford.edu>
# Copyright (C) 2002 Karl E. Jørgensen <karl@jorgensen.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software

set -e

prefix=/usr
libdir=${prefix}/share/battery-stats

TEMP=`getopt -o f:s:t:d:TAg:D --long from:,since:,to:,duration:,text,norate,title:,geometry:,display:,libdir: -n battery-graph -- "$@"`

now=$( date +%s --date=now ) 

from=0
to=0
duration=0
default_duration=10800 # 3 hours
text=false
SWITCH_RATE=true
title="Battery Graph"

eval set -- "$TEMP"
while true ; do
    case "$1" in
	-f|--from)
	    from=`date --date="$2" +%s`
	    shift 2
	    ;;
	-s|--since)
	    from=`date --date="$2" +%s`
	    shift 2
	    to=`date --date=now +%s`
	    ;;
	    
	-t|--to)
	    to=`date --date="$2" +%s`
	    shift 2
	    ;;
	-d|--duration)
	    case "$2" in
		*s) duration=$(basename $2 s) ;;
		*m) duration=$(( $(basename $2 m) * 60 )) ;;
		*h) duration=$(( $(basename $2 h) * 60 * 60 )) ;;
		*d) duration=$(( $(basename $2 d) * 24 * 60 * 60 )) ;;
		*w) duration=$(( $(basename $2 w) * 24 * 60 * 60 * 7 )) ;;
		*) duration=$(( $2 * 60 )) ;;
	    esac
	    shift 2;
	    ;;
	-T)
	    echo 1>&2 battery-graph: Warning: Deprecated option "$1": Use --text instead
	    text=true;
	    shift
	    ;;
	--text)
	    text=true;
	    shift
	    ;;
	--norate)
	    SWITCH_RATE=false;
	    shift
	    ;;
	-D|--display)
	    DISPLAY=$2
	    export DISPLAY
	    shift 2
	    text=false
	    ;;
	-g|--geometry)
	    geometry=$2
	    shift 2
	    text=false
	    ;;
	--title)
	    title="$2"
	    shift 2
	    text=false
	    ;;
	--libdir)
	    libdir="$2"
	    shift 2
	    ;;
	--)
	    shift
	    break;
	    ;;
	*)
	    echo 1>&2 $0: Internal error - please report as bug '[Parsing args]'
	    exit 2;
    esac
done

if [ -z "$DISPLAY" ] ; then
    text=true
fi

if [ $from -eq 0 ] && [ $duration -eq 0 ] && [ $to -eq 0 ] 
then
    # No options specified at all. 
    duration=$default_duration
    to=$now
fi

case "${from}:${duration}:${to}" in
    0:0:*)	# Only 'to' given
	from=$(( $to - $default_duration ))
	;;
    0:*:0)	# Only duration given
	to=$now
	from=$(( $to - $duration ))
	;;
    0:*:*)	# Only 'duration' and 'to' given
	from=$(( $to - $duration ))
	;;
    *:0:0)	# Only 'from' given
	to=$(( $from + $default_duration ))
	;;
    *:0:*)	# Only 'from' and 'to' given. Great!
	;;
    *:*:0)	# Only 'from' and 'duration' given
	to=$(( $from + $duration ))
	;;
    *:*:*)	# All 3 specified. Make sure that they match up
	if [ $(( $from + $duration )) -ne $to ] ; then
	    echo $0: Inconsistent from/to/duration: $from/$to/$duration
	    exit 2
	fi
	;;
    *)
	echo $0: Internal error - please report bug 1>&2 '[Time calculation]'
	exit 2
esac

# So far, $from and $to are 'seconds since 1st Jan 1970 00:00:00 UTC'.
# But gnuplot uses 'seconds since '1st Jan 2000 00:00:00 UTC'...

adjustment=$(( $(TZ=UTC date +%s --date='1/1/2000') - $(TZ=UTC date +%s --date='1/1/1970') ))

# Adjustment between UTC and local time
utc_adjust=$(( $( date -u --date=12:00 +%s) - $(date --date=12:00 +%s) ))

adjustment=$(( $adjustment - $utc_adjust ))

from2000=$(( $from - $adjustment ))
to2000=$(( $to - $adjustment ))

TMPFILENAME=`mktemp`

# Write battery log to tmp file which allows us to do some more fancy plotting and fitting
battery-log "$@" > $TMPFILENAME



# Extract time of last charge status change
TIME_LAST_RECORD=`tail -n 1 $TMPFILENAME | awk '{ print $1 }'`
TIME_LAST_DISCHARGE_BEGIN=`awk "BEGIN {last_status=-1} \
{ if (\\\$3!=last_status && \\\$3==1) {tchange = \\\$1} last_status=\\\$3 } \
END {print (tchange)}" $TMPFILENAME`

if [ ! "$TIME_LAST_DISCHARGE_BEGIN" ] ; then
    SWITCH_RATE=false
else
    TIME_LAST_DISCHARGE_END=`awk "BEGIN {last_status=-1} \
{ if (\\\$3!=last_status && \\\$3==2) {tchange = \\\$1} last_status=\\\$3 } \
	END { if (tchange>$TIME_LAST_DISCHARGE_BEGIN) {print (tchange)} 
	else {print $TIME_LAST_RECORD} }" $TMPFILENAME`
fi
ZERO_BIOS_ESTIMATE=`tail -n 1 $TMPFILENAME | awk '{ print $6 }'`


(   
    if $text ; then
	echo set terminal dumb ${COLUMNS:-$(tput cols)} ${LINES:-$(tput lines)}
    fi

    echo call \"${libdir}/graph-setup\" 

	# Fitting last discharge segment if SWITCH_RATE is true
	echo "zero_time=0" # avoid undefined errors if no slope is computed
	echo "full_time = 1"
	echo "zero_time_err=0"
	echo "A = 50.0"
	echo "B = 1.0"
	echo "B_err = 0.0" 
	echo "f(x) = A+B*x"
	echo "g(x) = 0"

    if $SWITCH_RATE ; then
	echo "if ($TIME_LAST_DISCHARGE_END>$TIME_LAST_DISCHARGE_BEGIN) { " # makes sure we have a positive interval
	echo "set fit errorvariables"
	echo "set fit quiet"
	echo "fit [0: ($TIME_LAST_DISCHARGE_END-$TIME_LAST_DISCHARGE_BEGIN)] f(x) \"$TMPFILENAME\" using (\$1 - $TIME_LAST_DISCHARGE_BEGIN ):2 via A,B"
	echo "zero_time = -A/B"
	echo "zero_time_err = sqrt((A/B**2*B_err)**2+(1.0/B*A_err)**2) }" # in case we want to display estimated time left
	echo "full_time = (100-A)/B"
	echo "g(x) = x<zero_time?(x>full_time?f(x):1/0):1/0"
    fi

    echo "set xrange [ $from2000 : $to2000 ] noreverse"
	echo plot "\"$TMPFILENAME\" using (\$1 - $adjustment):(\$3==2?\$2:1/0) smooth unique axis x1y1 title \"Plugged in\" with lines linecolor rgb \"blue\" linewidth 3, \
	\"\" using (\$1 - $adjustment):(\$3==1?\$2:1/0) smooth unique axis x1y1 title \"Discharging\" with lines linecolor rgb \"red\" linewidth 3 \\"
    if $SWITCH_RATE ; then 
		echo ", g(x -($TIME_LAST_DISCHARGE_BEGIN-$adjustment) ) title (B<0?sprintf(\"slope= (%.2f +/- %.2f) %/h\", B*3600, B_err*3600):\"\") lc rgb \"black\" lt 2 "
    fi
    
)  | gnuplot -persist ${geometry:+-geometry} $geometry ${title:+-title} "${title}" ; rm -f $TMPFILENAME


# TODO Have to decide if we want to clean up or leave the file for us to zoom in/out in the graph
# For now we will just go the clean way and delete everything again.
rm -f $TMPFILENAME
