## Yolanda, a video CMS for the web
## Copyright (C) 2007, 2008 Nils Dagsson Moskopp, Johannes Schauer

## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU Affero General Public License as
## published by the Free Software Foundation, either version 3 of the
## License, or (at your option) any later version.

## This program 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 Affero General Public License for more details.

## You should have received a copy of the GNU Affero General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.

import logging

from yolanda.lib.base import *
from yolanda.lib.gstreamer import info, snapshot, encode

import os
import hashlib
import threading

from datetime import datetime, timedelta

log = logging.getLogger(__name__)

class UploadController(BaseController):

    def index(self):
        return render('/xhtml/upload.mako')

    def upload(self):
        upload = request.params['file'] # request.param.get('file') is better maybe, doesn't raise a KeyError exception

        # check if file is video
        videoinfo = info.Info(upload.file)
        if not videoinfo.get_info():
            c.message = {
                        'type': 'error',
                        'text': 'Your file was not recognized as a video. Go figure.'
                        }
            return render('/xhtml/upload.mako')

        # check if file is duplicate
        upload.file.seek(0)
        sha256 = hashlib.sha256(upload.file.read(1024*1024)).hexdigest()

#        if model.Video.query.filter_by(sha256=sha256).count():
#            c.message = {
#                        'type': 'error',
#                        'text': 'Your file was already uploaded. Go away.'
#                        }
#            return render('/xhtml/upload.mako')

        # TODO: set up safeguards against omitted / wrong data

        # set up database entry

#        raise RuntimeError

        video = model.Video(

            # Dublin Core terms
            dc_title = request.params['dc_title'],
            dc_alternative = request.params['dc_title'],

#            dc_subject = [model.DC_Subject(name=u'lol'), model.DC_Subject(name=u'wut')],
            dc_subject = self.getsubjects(),
#            dc_creator = model.DC_Creator(name = request.params['dc_creator']),

            dc_abstract = request.params['dc_abstract'],

            # TODO: enable several contributors
#            dc_contributor = [model.DC_Contributor(name=contributor.lstrip()) for contributor in  request.params['dc_contributor'].split(',')],
#            dc_contributor = [model.DC_Contributor(name=u'lol'), model.DC_Contributor(name=u'wut')],

            # TODO: insert real data
            dc_created = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_valid = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_available = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_issued = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_modified = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_dateAccepted = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_dateCopyrighted = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),
            dc_dateSubmitted = datetime.now().strftime("%Y-%m-%d %H:%M:%S"),

            dc_identifier = '',
            dc_source = '',
            dc_language = request.params['dc_language'],

            # TODO: insert videolength
            dc_extent = timedelta(0),

            dc_spatial = request.params['dc_spatial'],
            dc_temporal = datetime(9999,9,9).strftime("%Y-%m-%d %H:%M:%S"),

            dc_rightsHolder = '',

            # Creative Commons properties
            cc_commercial = (request.params['commercial'] == 'cc_commercial'),
            cc_sharealike = (request.params['modification'] == 'cc_sharealike'),
            cc_derivatives = (request.params['modification'] != 'cc_noderivatives'),

            sha256=sha256
            )

        model.session.commit()

        # copy file to temporary destination
        temp_file = open(os.path.join(config['cache.dir'], str(video.id)), 'w')
        upload.file.seek(0)
        u.copyfileobj(upload.file, temp_file)
        upload.file.close()
        temp_file.close()

        # define stuff
        videosource=os.path.join(config['cache.dir'], str(video.id))
        videodestination=os.path.join(config['pylons.paths']['static_files'], config['directory_videos'], str(video.id))
        snapshotdestination=os.path.join(config['pylons.paths']['static_files'], config['directory_video-stills'], str(video.id))
        thumbnaildestination=os.path.join(config['pylons.paths']['static_files'], config['directory_video-thumbnails'], str(video.id))

        # start encoding thread in background
        threading.Thread(target=self.bgencode, args=(videosource, videodestination, snapshotdestination, thumbnaildestination)).start()

        # return 'Successfully uploaded: %s'%video.query.all()
        c.message = {
                    'type': 'information',
                    'text': ''
                    }
        c.message['text']='Your file was successfully uploaded to "%s".'%videodestination
        return render('/xhtml/index.mako')

    def bgencode(self, source, destination, snapshotdestination, thumbnaildestination):
        videosnapshot = snapshot.Snapshot(source).get_snapshot()
        videosnapshot.save(snapshotdestination, 'JPEG')
        videosnapshot.thumbnail((300,150))
        videosnapshot.save(thumbnaildestination, 'JPEG')
        videoencode = encode.Encode(source,destination)
        videoencode.run()
        os.unlink(source)

    def getsubjects(self):
        dc_subject = []
        for subject in  request.params['dc_subject'].split(','):
            s = model.DC_Subject.get_by(name=subject.lstrip())
            if s:
                dc_subject.append(s)
            else:
                dc_subject.append(model.DC_Subject(name=subject.lstrip()))
        return dc_subject
