##########################################################
# MOTH_TIMECODE.PY - General Purpose Python Timecode Class
# Version 0.30, June 16th 2009
#
# www.mothcatcher.co.uk


# Sample Usage:
#
#       from Moth_Timecode import *
#       TC_1 = Timecode( "01:00:00:00" )
#       TC_2 = Timecode( 0, 1, 1, 1 )
#       TC_3 = Timecode( TC_2 )
#       if TC_1 > TC_2:
#               print TC_1 + TC_2 + TC_3
#
#       >>> 01:02:02:02



class Timecode:

        def __init__( self, TC_or_Hours=0, Minutes=0, Seconds=0, Frames=0 ):
                self.FPS = 25
                self.FrameDeliminator = ":"
            
                table = {       'Frames':       { 'base':self.FPS,  'ripple':'Seconds' },
                                'Seconds':      { 'base':60,        'ripple':'Minutes' },
                                'Minutes':      { 'base':60,        'ripple':'Hours' },
                                'Hours':        { 'base':24,        'ripple':'' },
                } 
                
                if isinstance( TC_or_Hours, Timecode ): 
                        self.Hours =    TC_or_Hours.Hours
                        self.Minutes =  TC_or_Hours.Minutes
                        self.Seconds =  TC_or_Hours.Seconds
                        self.Frames =   TC_or_Hours.Frames
                        
                elif isinstance( TC_or_Hours, str ):
                        TC_or_Hours = self.ForceDeliminatorsToColon( TC_or_Hours )
                        Split = TC_or_Hours.split( ':' )
                        self.Hours =    int(Split[0])
                        self.Minutes =  int(Split[1])
                        self.Seconds =  int(Split[2])
                        self.Frames =   int(Split[3])
                        
                else:
                        self.Hours =    TC_or_Hours
                        self.Minutes =  Minutes
                        self.Seconds =  Seconds
                        self.Frames =   Frames

        def ForceDeliminatorsToColon( self, thistext ):
            result = thistext.replace( '.', ':' )
            result = result.replace( ';', ':' )
            result = result.replace( ',', ':' )
            result = result.replace( ':', ':' )
            return result

        def ToFrames( self ):
            result = self.Hours * 60 * 60 * self.FPS
            result += self.Minutes * 60 * self.FPS
            result += self.Seconds * self.FPS
            result += self.Frames
            return result

        def FromFrames( self, frames ):
            frames = int(frames)
            self.Hours = frames // (60*60*self.FPS)
            self.Minutes = (frames // (60*self.FPS)) % 60
            self.Seconds = (((frames // (self.FPS)) % 60) % 60)
            self.Frames = frames % self.FPS % 60 % 60
            return self

        def SetFrameDeliminator( self, newDelim ):
            self.FrameDeliminator = newDelim


        def ToString( self ):
                return "%02d:%02d:%02d:%02d" % ( self.Hours, self.Minutes, self.Seconds, self.Frames )

        def ToTime( self ):
                output = ""
                started = False

                if self.Hours > 0 or started:
                        output += "%s:" % self.Hours
                        started = True

                if self.Minutes > 0 or started:
                        output += "%s:" % self.Minutes

                output += "%s:%02d" % ( self.Seconds, self.Frames )

                return output

        def __str__(self):
                return self.ToString()

        def __add__(self, other):
            if isinstance( other, Timecode ):
                return Timecode().FromFrames( self.ToFrames() + other.ToFrames() )
            else:
                return Timecode().FromFrames( self.ToFrames() + float(other) )

        def __mul__(self, other):
            if isinstance( other, Timecode ):
                return Timecode().FromFrames( self.ToFrames() * other.ToFrames() )
            else:
                return Timecode().FromFrames( self.ToFrames() * float(other) )

        def __div__(self, other):
            if isinstance( other, Timecode ):
                return Timecode().FromFrames( self.ToFrames() / other.ToFrames() )
            else:
                return Timecode().FromFrames( self.ToFrames() / float(other) )
            
        def __sub__(self, other):
            if isinstance( other, Timecode ):
                return Timecode().FromFrames( self.ToFrames() - other.ToFrames() )
            else:
                return Timecode().FromFrames( self.ToFrames() - float(other) )

        def __cmp__(self, other):
            if not isinstance( other, Timecode ):
                other = Timecode( other )
        
            AFrames = self.ToFrames()
            BFrames = other.ToFrames()

            if AFrames == BFrames: return 0
            if AFrames < BFrames: return -1
            if AFrames > BFrames: return 1              

        def offsetX ( self, attribute, offset ):
                if attribute == "":
                        return

                x = getattr( self, attribute )
                x += offset

                while ( x >= self.table[attribute]['base'] ):
                        x -= self.table[attribute]['base']
                        self.offsetX( self.table[attribute]['ripple'], 1 )

                while ( x < 0 ):
                        x += self.table[attribute]['base']
                        self.offsetX( self.table[attribute]['ripple'], -1 )

                setattr( self, attribute, x )   

        def offset ( self, Hours, Minutes, Seconds, Frames ):
                self.offsetX ( 'Frames', Frames )
                self.offsetX ( 'Seconds', Seconds )
                self.offsetX ( 'Minutes', Minutes )
                self.offsetX ( 'Hours', Hours )
                return self

        def SetFPS( self, FPS ):
            self.FPS = FPS
            return self

        def ScaleFPS( self, FPS ):
            self.Frames = int(round((float(self.Frames)/float(self.FPS))*FPS))
            self.FPS = FPS
            return self


class TimecodeRange:
        def __init__( self, Start=Timecode(  ), End=Timecode(  ), Data="" ):
                self.Start = Start
                self.End = End
                self.Length = End - Start
                self.Data = Data

        def __str__( self ):
                return "%s => %s %s (%s)" % ( self.Start, self.End, self.Data, self.Length )


