#!/usr/bin/python
# -*- coding:utf-8 -*-

# Maintainer: Pablo Saavedra
# Contact: pablo.saavedra@interoud.com

import os
import sys

reload(sys)
sys.setdefaultencoding('utf-8')

from httplib2 import Http
from urllib import urlencode
from optparse import OptionParser
from slugify import slugify
from threading import Thread
import ConfigParser
import simplejson as json
import subprocess



def get_http_requester():
    try:
        h = Http(timeout=10)
    except Exception:
        h = Http()
    return h

DEV_NULL=open('/dev/null', "w")

hostname = "localhost"
port = "80"
storage_base_dir = "/storage/videos"
token = "token"
ssl = False
logfile = "/dev/stdout"
loglevel = 20

# command line options parser ##################################################

parser = OptionParser()
parser.add_option("-H", "--hostname", 
        dest="hostname", default=hostname,
        help="LiveR hostname (default: %s)" % hostname)
parser.add_option("-P", "--port", 
        dest="port", help="LiveR port number (default: %s)" % port, 
        default=port)
parser.add_option("-l", "--logfile",
        dest="logfile", help="Log file (default: %s)" % logfile,
        default=logfile)
parser.add_option("--loglevel",
        dest="loglevel", help="Log level (default: %s)" % loglevel,
        default=loglevel)
parser.add_option("-t", "--token",
        dest="token", help="Token for LiveR access (default: %s)" % token,
        default=token)
parser.add_option("--storagebasedir", 
        dest="storage_base_dir", help="Storage basedir (default: %s)" % storage_base_dir,
        default=storage_base_dir)
parser.add_option("--ssl", 
        dest="ssl", help="SSL ON/OFF (default: %s)" % ssl,
        action="store_true",
        default=ssl)
(options, args) = parser.parse_args()

hostname = options.hostname
print hostname
port = options.port
storage_base_dir = os.path.abspath(options.storage_base_dir)
token = options.token
ssl = options.ssl
logfile = options.logfile
loglevel = options.loglevel


# classes ######################################################################

class ffmpegRunner(Thread):

    def __init__ (self,ffmpeg_params):
        Thread.__init__(self)
        self.name = ffmpeg_params["name"]
        self.ffmpeg = None
        self.ffmpeg_params = ffmpeg_params

    def run (self):
        logger.info("starting ffmpeg thread for %s stream: %s" \
                % (self.name,self.ffmpeg_params))

        cmd = "/usr/bin/avconv -y -i %(uri)s -t %(duration)s -vcodec copy -acodec copy %(destination)s" % self.ffmpeg_params
        logger.debug("cmd: %s" % cmd)
        self.ffmpeg = subprocess.Popen(cmd.split(), shell=False, bufsize=1024,
                stdin=subprocess.PIPE, stdout=DEV_NULL,
                stderr=DEV_NULL, close_fds=True)
        p = self.ffmpeg
        logger.info("launched ffmpeg for %s stream (%s)" \
                % (self.name,str(p.pid)))
        p.wait()
        logger.info("ending ffmpeg for %s stream (%s)"
                % (self.name,str(p.pid)))
        self.ffmpeg_params["result"] = p.returncode

        cmd = "/usr/local/bin/qtfaststart %(destination)s" % self.ffmpeg_params
        logger.debug("cmd: %s" % cmd)
        self.ffmpeg = subprocess.Popen(cmd.split(), shell=False, bufsize=1024,
                stdin=subprocess.PIPE, stdout=DEV_NULL,
                stderr=DEV_NULL, close_fds=True)
        p = self.ffmpeg
        logger.info("launched qtfaststart for %s stream (%s)" \
                % (self.name,str(p.pid)))
        p.wait()
        logger.info("ending qtfaststart for %s stream (%s)"
                % (self.name,str(p.pid)))


# logging ######################################################################
import logging
hdlr = logging.FileHandler(logfile)
hdlr.setFormatter(logging.Formatter('%(levelname)s %(asctime)s %(message)s'))
logger = logging.getLogger('liver')
logger.addHandler(hdlr)
logger.setLevel(int(loglevel))

# setting up ###################################################################

logger.info("Default encoding: %s" % sys.getdefaultencoding())

liver_http_base="http://" + hostname + ":" + port
if ssl:
    liver_http_base="https://" + hostname + ":" + port
logger.info("LiveR base URL: %s" % liver_http_base)

getJobURL = "%s/liver/api/external/get_worker_jobs?token=%s" % ( liver_http_base,token )
notifyJobURL = "%s/liver/api/external/notify_worker_jobs_result?token=%s" % ( liver_http_base, token )

headers = {'User-Agent': 'job notifier'}


while True:
    try:
        logger.info("Requesting for new jobs")
        h = get_http_requester()
        resp, content = h.request(getJobURL, "GET", None , headers=headers)

        logger.debug("Response: %s" % resp)
        logger.debug("Content: %s" % content)

        j_content=json.loads(content)

    except Exception, e:
        logger.error("Unexpected error getting JSON jobs: %s" % str(e))
        sys.exit(-1)

    try:
        json_result = j_content['result']
        logger.debug("Result: %s" % json_result)
        json_response = j_content['response']
        logger.debug("Response: %s" % json_response)
    except Exception, e:
        logger.error("Non valid JSON: %s" % str(e))
        sys.exit(-1)

    if json_result == -2:
        break

    FFMPEG_THREADS=[]
    try:
        if j_content['result'] == 0:
            logger.info( "Parsing and doing jobs")
            for job_dict in json_response.values():
                job_dict['result']=0
                job_id=job_dict['id']
                job_start=job_dict['start']
                job_duration=job_dict['duration']
                profiles=job_dict['profiles']
                for p in profiles:
                    # p['id']
                    # p['uri']
                    params=p
                    params["job_id"]=job_id
                    params["job_start"]=job_start
                    params["job_duration"]=job_duration
                    params["name"]=\
                      slugify(p["uri"]) + "_" + str(job_start) + "_" + str(job_duration) + ".mp4"
                    params["destination"]=storage_base_dir + "/" + params["name"]
                    params["duration"]=job_duration

                    t = ffmpegRunner(params)
                    t.start()
                    FFMPEG_THREADS.append(t)


    except Exception, e:
        logger.error("Unexpected error: %s" % str(e))
        sys.exit(-1)

    j_content['result']=0
    for f in FFMPEG_THREADS:
        f.join()
        if f.ffmpeg_params['result'] != 0:
            j_content['result']=f.ffmpeg_params['result']
            j_content['response'][f.ffmpeg_params['job_id']]['response']=f.ffmpeg_params['result']
    j_content['jobs'] = j_content.pop('response')

    try:
        logger.info("Posting results")
        logger.debug("j_content: %s" % j_content)
        json_ret=json.dumps(j_content)
        # json_ret=urlencode({"argv":json_ret})

        h = get_http_requester()
        resp, content = h.request(notifyJobURL, "POST", json_ret , headers=headers)
        logger.debug("Response: %s" % resp)
        logger.debug("Content: %s" % content)
    except Exception, e:
        logger.error("Results can not be submitted to the server: %s" % str(e))
        sys.exit(-1)



