# -*- coding: ascii -*-

###########################################################################
# clive, video extraction utility
# Copyright (C) 2007-2008 Toni Gundogdu
#
# This file is part of clive.
#
# clive 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 3 of the License, or
# (at your option) any later version.
#
# clive 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 clive.  If not, see <http://www.gnu.org/licenses/>.
###########################################################################

## The classes used to represent data transfer progress

# Do not cache these imports: they are not used in any other files
import math

__all__ = ['Progress', 'ProgressVerify']

from clive.opts import Options
from clive.modules import Modules

## The class used for file transfers
class Progress:

    ## Constructor
    def __init__(self, v_info=None):
        self._opts = Options()._opts
        self._v_info = v_info

    ## Callback method for urlgrabber
    def start(self, filename, url, basename, length, text):
        self._filename = filename
        self._url = url
        self._basename = basename
        self._length = length
        self._time = Modules().getinst('time')
        self._tstarted = self._time.time()
        self._tthen = self._time.time()
        self._num_bspaces = 0

    ## Callback method for urlgrabber
    def update(self, read, end=0):
        if not end:
            elapsed = self._time.time() - self._tthen
            if elapsed < 1.0: return

        os = Modules().getinst('os')
        text = os.path.basename(self._filename)[:44].ljust(44)

        progress = self._percent(read, self._length)
        if progress > 0: text += ('%d%%' % progress).rjust(6)
        else: text += ''.rjust(6)

        text += self._byteshuman(self._length).rjust(9)

        elapsed = self._time.time() - self._tstarted
        rate = (read - self._v_info['offset']) / elapsed
        left = (self._length - read) / rate
        t = [left,elapsed][end]
        gmt = self._time.gmtime(t)
        eta = '%02d:%02d:%02d' % (gmt[3], gmt[4], gmt[5])
        text += (self._byteshuman(rate) + '/s').rjust(11)
        text += eta.rjust(9)

        self._write_bspaced(text)
        self._tthen = self._time.time()

    ## Callback method for urlgrabber
    def end(self, total):
        if total == self._v_info['length_bytes']:
            self.update(total, end=1)
        self._write_stdout('\n')
    
    def _percent(self, i, j):
        if not i or not j: return 0
        return int(float(i) / float(j) * 100)

    def _byteshuman(self, bytes):
        a = ['B','KB','MB','GB','TB']
        try:
            i = int(math.floor(math.log(bytes,1024)))
            b = round(float(bytes/math.pow(1024,i)),2)
        except OverflowError:
            i = 0; b = 0;
        return '%.1f%s' % (b,a[i])

    def _write_bspaced(self, text):
        bspaces = ''
        if self._num_bspaces > 0:
            bspaces = '\b' * self._num_bspaces
        self._write_stdout(bspaces + text)
        self._num_bspaces = len(text)
    
    def _write_stdout(self, text):
        if self._opts.enable_verbose:
            sys = Modules().getinst('sys')
            sys.stdout.write(text)
            sys.stdout.flush()


## The class used for video page (HTML) transfers
class ProgressVerify(Progress):

    ## Constructor
    def __init__(self, index):
        self._opts = Options()._opts
        self._index = index

    ## Prints out a line using cached data
    def from_cache(self, url, row):
        self._url = url
        self._length = row['cache_length']
        self.update(self._length, cached=1)

    ## Callback method for urlgrabber
    def update(self, read, cached=0):
        if read == 0: return

        text = self._url[:63].ljust(63)
        progress = self._percent(read, self._length)

        if not cached:
            if progress > 0: s = '%d%%' % progress
            else: s = self._byteshuman(read)
        else:
            s = '(cache)'

        if self._index[1] > 1: # Multiple URLs
            text += s.rjust(8)
            text += ('%d/%d' % (self._index[0]+1, \
                self._index[1])).rjust(8)
        else:
            text += s.rjust(16)

        if not cached:
            self._write_bspaced(text)
        else:
            self._write_stdout(text)


