#!/tvbin/tivosh 
#
#
# Tracker Update TCL module for CRON invokation
#
# Based on Tracker version 3.0.1b1 by Stuart Anderton, 4/11/04
#
#
# Created by Chris Stennett 13 Sep 05
#
#



#####################################################
## Tracker Initialize Procedure 
##
## Used as is - no changes or additions.

proc tracker_init {} {
  
  global db
  global trackerdir
  global lastupdate
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global t_selectiontypes
  global ignoregenerics
  
  set trackerdir "/var/hack/tracker"
  set t_selectiontypes "{Show Recommendation} {Package Recommendation} Manual Manual Manual Suggestion Suggestion Bookmark {Season Pass} {Season Pass} Guide Manual WishList WishList ManualExtended CaptureRequest DailyData"
  
  if {![file exists $trackerdir]} {
    file mkdir $trackerdir
  }
  
  #defaults
  set lastupdate 0
  set blockwatchedID 1
  set blockunwatchedID 1
  set blockwatchedTD 0
  set blockunwatchedTD 0
  set ignoregenerics 1
  
  if {![file exists $trackerdir/tracker.cfg]} {
    tracker_saveconfig
  }
  tracker_loadconfig
}


#####################################################
## Tracker Load Configuration Procedure
##
## Used as is - no changes or additions.

proc tracker_loadconfig {} {
  
  global trackerdir
  global lastupdate
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global ignoregenerics
  
  set config [open $trackerdir/tracker.cfg r]
  set settings [read $config]
  close $config
  eval $settings
  
}


#####################################################
## Tracker Save Configuration Procedure
##
## Used as is - no changes or additions.

proc tracker_saveconfig {} {
  global trackerdir
  global lastupdate
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global ignoregenerics
  
  if {[file exists $trackerdir/tracker.cfg]} {
    file rename -force $trackerdir/tracker.cfg $trackerdir/tracker.cfg.bak
  }
  
  set config [open $trackerdir/tracker.cfg w]
  puts $config "set lastupdate $lastupdate ;"
  puts $config "set blockwatchedID $blockwatchedID ;"
  puts $config "set blockunwatchedID $blockunwatchedID ;"
  puts $config "set blockwatchedTD $blockwatchedTD ;"
  puts $config "set blockunwatchedTD $blockunwatchedTD ;"
  puts $config "set ignoregenerics $ignoregenerics ;"
  close $config
}


#####################################################
## Tracker Update Procedure
##
## Slight modifications to incoming arguments to enable
## being called as a straight tcl module. Also 
## removed "puts" line items as no longer required.
## Added database handling and defined global variables
## as required.
##

proc tracker_update {} {
  
  global db
  global trackerdir
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global ignoregenerics
  global lastupdate 
  global t_selectiontypes
  global dbPoolSize
  
  set dbPoolSize [expr 100 * 1024]
  
  set db [dbopen $dbPoolSize]
  
  scan_cancelled $lastupdate
  set lastupdate [clock seconds]
  tracker_saveconfig
  
  dbclose $db
  
}


#####################################################
## Tracker Scan Cancelled Procedure
##
## Used as is - no changes or additions.

proc scan_cancelled { since } {
  
  global db
  global trackerdir
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global ignoregenerics
  
  ForeachChangedMfsFileTrans fsid name type "/Recording/Cancelled" $since 10 {
    
    if {[lindex [split $name :] 0] <= [expr [clock seconds] / 86400]} {
      set item [db $db openid $fsid]
      set cancelreason [dbobj $item get CancelReason]
      
      if {$cancelreason == 24 || $cancelreason == 6 || $cancelreason == 12 || $cancelreason == 33} {
        
        set type [dbobj $item get SelectionType]
        set showing [dbobj $item get Showing]
        set program [dbobj $showing get Program]
        set episodetmsid [dbobj $program get TmsId]
        set seriestitle [dbobj $program get Title]
        set series [dbobj $program get Series]
        set recdate [dbobj $showing get Date]
        set eptitle [dbobj $program get EpisodeTitle]
        
        if {$series != ""} {
          set seriestmsid [dbobj $series get TmsId]
          set isepisodic [dbobj $series get Episodic]
        } else {
          set seriestmsid ""
          set isepisodic ""
        }
        
        if {$eptitle == ""} {
          set eptitle [clock format [expr $recdate * 86400] -format "%a %d-%m-%y"]
        }
        
        if {[regexp {.*0000$} $episodetmsid] == 1} {
          set eptitle "Generic"
        }
        
        if {$cancelreason == 6 || $cancelreason == 33} {
          set deletedby "TiVo"
        } else {
          set deletedby "User"
        }
        
        set secswatched [dbobj $item get NSecondsWatched]
        
        if {$secswatched > 0} {
          set watched "Watched ([expr $secswatched/60]mins)"
        } else {
          set watched "Unwatched"
        }
        set ismatch [regexp MV $seriestmsid match]
        
        if {$isepisodic != 1 && $ismatch != 1} {
          set seriestmsid "SP"
          set eptitle $seriestitle
          set seriestitle "Specials and One-offs"
        }
        
        if {$ismatch == 1} {
          set seriestmsid "MV"
          set eptitle $seriestitle
          set seriestitle "Films"
        }
        
        if {$seriestmsid == "" } {
          set seriestmsid "Unknown"
          set seriestitle "Unknown"
        }
        
        if {[file exists "$trackerdir/series"]} {
          
          set serieslist [open "$trackerdir/series" r]
          
          set isinlist 0
          
          while {![eof $serieslist]} {
            if {[lindex [gets $serieslist] 0] == $seriestmsid} {
              set isinlist 1
            }
          }
          
          close $serieslist
          set serieslist [open "$trackerdir/series" a]
          
        } else {
          set isinlist 0
          set serieslist [open "$trackerdir/series" w]
        }
        
        if {$isinlist == 0} {
          set listitem {}
          lappend listitem $seriestmsid
          lappend listitem $seriestitle
          lappend listitem $blockwatchedID
          lappend listitem $blockunwatchedID
          lappend listitem $blockwatchedTD
          lappend listitem $blockunwatchedTD
          puts $serieslist $listitem
        }
        
        close $serieslist
        
        updatetrack $seriestmsid $episodetmsid $eptitle $recdate $type 2 $deletedby $watched
        
      }
    }
    
    
  }
  return 0
}


#####################################################
## Tracker Update Track Procedure
##
## Used as is - no changes or additions.

proc updatetrack {seriestmsid episodetmsid title recdate type blocked deletedby watched} {
  
  global trackerdir
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global ignoregenerics
  
  #  Update viewable list
  
  if {[file exists "$trackerdir/$seriestmsid"]} {
    
    set episodelist [open "$trackerdir/$seriestmsid" r]
    set neweplist {}
    set match 0
    
    while {![eof $episodelist]} {
      
      set episode [gets $episodelist]
      
      if {[lindex $episode 0] == ""} {
        continue
      }
      
      if {[lindex $episode 0] == $episodetmsid} {
        set newitem {}
        lappend newitem [lindex $episode 0]
        lappend newitem [lindex $episode 1]
        
        if {$recdate == "" } {
          lappend newitem [lindex $episode 2]
        } else {
          lappend newitem $recdate
        }
        
        if {$type == "" } {
          lappend newitem [lindex $episode 3]
        } else {
          lappend newitem $type
        }
        
        if {$blocked == "" } {
          lappend newitem [lindex $episode 4]
        } else {
          lappend newitem $blocked
        }
        
        if {$deletedby == "" } {
          lappend newitem [lindex $episode 5]
        } else {
          lappend newitem $deletedby
        }
        
        if {$watched == "" } {
          lappend newitem [lindex $episode 6]
        } else {
          lappend newitem $watched
        }
        
        set match 1
        
      } else {
        set newitem {}
        lappend newitem [lindex $episode 0]
        lappend newitem [lindex $episode 1]
        lappend newitem [lindex $episode 2]
        lappend newitem [lindex $episode 3]
        lappend newitem [lindex $episode 4]
        lappend newitem [lindex $episode 5]
        lappend newitem [lindex $episode 6]
      }
      
      lappend neweplist $newitem
    }
    
    close $episodelist
    
    if {$match == 0} {
      set newitem {}
      lappend newitem $episodetmsid
      lappend newitem $title
      lappend newitem $recdate
      lappend newitem $type
      lappend newitem $blocked
      lappend newitem $deletedby
      lappend newitem $watched
      lappend neweplist $newitem
    }
    
    
    file rename -force $trackerdir/$seriestmsid $trackerdir/$seriestmsid.old
    
    set newepisodelist [open "$trackerdir/$seriestmsid" w]
    
    foreach line $neweplist {
      puts $newepisodelist $line
    }
    
    close $newepisodelist
    
  } else {
    
    set newitem {}
    lappend newitem $episodetmsid
    lappend newitem $title
    lappend newitem $recdate
    lappend newitem $type
    lappend newitem $blocked
    lappend newitem $deletedby
    lappend newitem $watched
    lappend neweplist $newitem
    
    set newepisodelist [open "$trackerdir/$seriestmsid" w]
    
    foreach line $neweplist {
      puts $newepisodelist $line
    }
    
    close $newepisodelist
    
  }
  
  # Update lists for blocking
  
  if {$deletedby == "TiVo" && $watched == "Unwatched"} {
    # add to blockunwatchedTDfile
    set openfile [open $trackerdir/block_UT a]
    puts $openfile $episodetmsid
    close $openfile
    return
  }
  
  if {$deletedby == "TiVo" && $watched != "Unwatched"} {
    # add to blockwatchedTDfile
    set openfile [open $trackerdir/block_WT a]
    puts $openfile $episodetmsid
    close $openfile
    return
    return
  }
  
  if {$deletedby == "User" && $watched == "Unwatched"} {
    # add to blockunwatchedIDfile
    set openfile [open $trackerdir/block_UU a]
    puts $openfile $episodetmsid
    close $openfile
    return
    return
  }
  
  if {$deletedby == "User" && $watched != "Unwatched"} {
    # add to blockwatchedIDfile
    set openfile [open $trackerdir/block_WU a]
    puts $openfile $episodetmsid
    close $openfile
    return
    return
  }
  
  
}

proc ForeachChangedMfsFileTrans { idVar nameVar typeVar dirName since count body } {
  global errorInfo errorCode
  
  upvar $idVar   id
  upvar $nameVar name
  upvar $typeVar type
  
  # Get the first batch of names
  RetryTransaction {
    if { [catch {mfs scan $dirName -start "" -count $count} batch] } {
      global errorCode errorInfo
      if { $errorCode == "errNmNameNotFound" } {
        return
      } else {
        error $batch $errorInfo $errorCode
      }
    }
  }
  
  set done 0
  while { [llength $batch] > 0 } {
    # Execute the body for each item in this batch
    RetryTransaction {
      foreach item $batch {
        set id   [lindex $item 0]
        set name [lindex $item 1]
        set type [lindex $item 2]
        
        
        # skip if unmodified
        if { [mfs moddate $id] < $since } {
          continue
        }
        
        set code [catch {uplevel $body} string]
        if { $code == 1 } {
          global errorCode errorInfo
          if { $errorCode == "errTmActiveLockConflict" ||
            $errorCode == "errTmBackgroundHoldoff" ||
            $errorCode == "errFsLockConflict" } {
            error $batch $errorInfo $errorCode
          } else {
            set done 2
            break
          }
        } elseif { $code == 3 } {
          # this is a break in the body.  just return normally
          set done 3
          break
        } elseif { $code != 0 } {
          set done 4
          break
        }
      }
    }
    
    switch -exact $done {
      1 {return}
      2 {return -code error -errorinfo $errorInfo \
            -errorcode $errorCode $string}
      3 {return}
      4 {return -code $code $string}
    }
    
    # Get the next batch
    set lastName [lindex [lindex $batch end] 1]
    RetryTransaction {
      set batch [mfs scan $dirName -start $lastName -count $count]
      if { $lastName == [lindex [lindex $batch 0] 1] } {
        set batch [lrange $batch 1 end]
      }
    }
  }
}

#####################################################
## Custom Code
##
## Custom code created to perform some setup,launch 
## the relevant procedures and handle some basic logging.

  global trackerdir
  global lastupdate
  global blockwatchedID
  global blockunwatchedID
  global blockwatchedTD
  global blockunwatchedTD
  global t_selectiontypes
  global ignoregenerics
  
  ## fool any called tivoweb modules that they are being called by tivoweb 
  ## (don't know whether required - but do it anyway)
  global reload
  global dlc
  set reload 1
  set dlc 1
  set channeltablefsid {}
  
  puts "---- Tracker For Cron"
  puts "started at [clock format [clock seconds] -format {%H:%M:%S} -gmt true]"
  
  ## call the required procedures
  puts "about to run tracker_init -->"
  tracker_init
  puts "<-- completed tracker_init"
  
  puts "about to run tracker_update -->"
  tracker_update
  puts "<-- completed tracker_update"
  
  puts "finished at [clock format [clock seconds] -format {%H:%M:%S} -gmt true]"

