#!/usr/bin/python

# Copyright (C) Michael Still (mikal@stillhq.com) 2006, 2007, 2008
# Released under the terms of the GNU GPL v2

# This file is the core of MythNetTV. It is intended that user interfaces call
# into this module to get things done, and then present their own interface in
# whatever manner makes sense to them

import gflags
import sys

import database
import program
import proxyhandler
import syndication
import video

gflags.DEFINE_boolean('oldestfirst', False,
                      'Download the oldest programs first')
gflags.DEFINE_boolean('newestfirst', False,
                      'Download the newest programs first')

gflags.DEFINE_boolean('verbose', False,
                      'Output verbose debugging information')
FLAGS = gflags.FLAGS

def NextDownloads(count, filter, subtitle, out=sys.stdout):
  """NextDownloads -- return a list of the GUIDs to download next. Optionally
     filter based on an exact match of title string.
  """

  db = database.MythNetTvDatabase()
  
  remaining = int(count)
  if FLAGS.oldestfirst and FLAGS.newestfirst:
    out.write('Cannot download both oldest and newest first!\n')
    return []

  old_target = remaining / 2
  if FLAGS.oldestfirst:
    old_target = remaining
  elif FLAGS.newestfirst:
    old_target = 0

  guids = []

  if filter == None:
    title = 'is not NULL'
  else:
    title = '= "%s"' % filter
    out.write('Download constrained to "%s"\n' % filter)

  if subtitle == None:
    subtitle_filter = '.*'
  else:
    subtitle_filter = subtitle

  subscription_titles = []
  inactive_titles = []
  for row in db.GetRows('select * from mythnettv_subscriptions'):
    if not row['inactive']:
      subscription_titles.append(row['title'])
      if FLAGS.verbose:
        out.write('  %s is active\n' % row['title'])

    else:
      inactive_titles.append(row['title'])
      if FLAGS.verbose:
        out.write('  %s is inactive\n' % row['title'])

  for row in db.GetRows('select * from mythnettv_programs where '
                        'download_finished is NULL and title %s '
                        'and subtitle rlike "%s" and inactive is null '
                        'order by date asc limit %d;'
                        %(title, subtitle_filter, old_target)):
    # We should only download shows we are _currently_ subscribed to
    if not row['title'] in inactive_titles:
      guids.append(row['guid'])
      remaining -= 1
      if FLAGS.verbose:
        print '  Adding %s : %s to the list of downloads' %(row['title'],
                                                            row['subtitle'])

  if FLAGS.verbose:
    out.write('\n')

  for row in db.GetRows('select * from mythnettv_programs where '
                        'download_finished is NULL and title %s '
                        'and subtitle rlike "%s" '
                        'and inactive is null '
                        'and guid not in ("%s") '
                        'order by date desc limit %d;'
                        %(title, subtitle_filter,
                          '", "'.join(guids), remaining)):
    # We should only download shows we are _currently_ subscribed to
    if not row['title'] in inactive_titles:
      guids.append(row['guid'])
      if FLAGS.verbose:
        print '  Adding %s : %s to the list of downloads' %(row['title'],
                                                            row['subtitle'])

  if FLAGS.verbose:
    out.write('\n')

  out.write('%d matches\n' % len(guids))
  return guids


def DownloadAndImport(db, guid, out=sys.stdout):
  """DownloadAndImport -- perform all the steps to download and import a
     given guid.
  """

  prog = program.MythNetTvProgram(db)
  try:
    out.write('\nDownloading %s\n' % guid)
    prog.Load(guid)
    if prog.Download(db.GetSettingWithDefault('datadir', FLAGS.datadir),
                     out=out) == True:
      out.write('Download OK\n')
      prog.Import(out=out)
      return True

  except program.DownloadBudgetExceededException, e:
    out.write('Download Error: %s\n' % e)
    if 'attempts' in prog.persistant and prog.persistant['attempts']:
      prog.persistant['attempts'] -= 1
      prog.Store()

  except Exception, e:
    out.write('Download Error: %s\n' % e)

  return False


def Subscribe(url, title):
  """Subscribe -- subscribe to a new RSS or ATOM feed"""
  
  db = database.MythNetTvDatabase()
  db.WriteOneRow('mythnettv_subscriptions', 'url', {'url':url,
                                                    'title':title,
                                                    'inactive':None})
  
def Update(out, title=None):
  """Update -- download updates for all feeds"""

  db = database.MythNetTvDatabase()
  title_sql = ''
  if title:
    title_sql = 'and title = "%s"' % title

  for row in db.GetRows('select * from mythnettv_subscriptions '
                        'where inactive is null %s'
                        % title_sql):
    if FLAGS.verbose:
      out.write('Updating: %s\n' % row['url'])

    try:
      proxy = proxyhandler.HttpHandler(db)
      xmlfile = proxy.Open(row['url'], out=out)
      syndication.Sync(db, xmlfile, row['title'], out=out)

    except Exception, e:
      out.write('Failed to update %s: %s\n' %(row['url'], e))
