# -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license

import logging

from flask import abort, current_app as app
from eve.utils import config
from apps.archive.common import copy_metadata_from_user_preferences
from superdesk.media.media_operations import process_file_from_stream, decode_metadata
from superdesk.media.renditions import generate_renditions, delete_file_on_error, get_renditions_spec
from superdesk.metadata.item import ITEM_STATE, CONTENT_STATE, ITEM_TYPE, CONTENT_TYPE
from superdesk.upload import url_for_media
from .common import update_dates_for, generate_guid, GUID_TAG, set_original_creator, \
    generate_unique_id_and_name, set_item_expiry
from superdesk.activity import add_activity
from superdesk.filemeta import set_filemeta
from superdesk.timer import timer
from superdesk.media.video_editor import VideoEditorWrapper

logger = logging.getLogger(__name__)


class ArchiveMediaService():
    video_editor = VideoEditorWrapper()

    type_av = {'image': CONTENT_TYPE.PICTURE, 'audio': CONTENT_TYPE.AUDIO, 'video': CONTENT_TYPE.VIDEO}

    def on_create(self, docs):
        """Create corresponding item on file upload."""

        for doc in docs:
            if 'media' not in doc or doc['media'] is None:
                abort(400, description="No media found")
            # check content type of video by python-magic
            content_type = app.media._get_mimetype(doc['media'])
            doc['media'].seek(0)
            file_type = content_type.split('/')[0]
            if file_type == 'video' and app.config.get("VIDEO_SERVER_ENABLED"):
                # upload media to video server
                res, renditions, metadata = self.upload_file_to_video_server(doc)
                # get thumbnails for timeline bar
                self.video_editor.create_timeline_thumbnails(doc.get('media'), 60)
            else:
                file, content_type, metadata = self.get_file_from_document(doc)
                inserted = [doc['media']]
                # if no_custom_crops is set to False the custom crops are generated automatically on media upload
                # see (SDESK-4742)
                rendition_spec = get_renditions_spec(no_custom_crops=app.config.get("NO_CUSTOM_CROPS"))
                with timer('archive:renditions'):
                    renditions = generate_renditions(file, doc['media'], inserted, file_type,
                                                     content_type, rendition_spec, url_for_media)
            try:
                self._set_metadata(doc)
                doc[ITEM_TYPE] = self.type_av.get(file_type)
                doc[ITEM_STATE] = CONTENT_STATE.PROGRESS
                doc['renditions'] = renditions
                doc['mimetype'] = content_type
                set_filemeta(doc, metadata)
                add_activity('upload', 'uploaded media {{ name }}',
                             'archive', item=doc,
                             name=doc.get('headline', doc.get('mimetype')),
                             renditions=doc.get('renditions'))
            except Exception as io:
                logger.exception(io)
                for file_id in inserted:
                    delete_file_on_error(doc, file_id)
                if res:
                    self.video_editor.delete(res.get('_id'))
                abort(500)

    def _set_metadata(self, doc):
        """
        Adds metadata to doc.
        """

        update_dates_for(doc)
        generate_unique_id_and_name(doc)
        doc['guid'] = generate_guid(type=GUID_TAG)
        doc.setdefault(config.ID_FIELD, doc['guid'])
        doc[config.VERSION] = 1
        set_item_expiry({}, doc)

        if not doc.get('_import', None):
            set_original_creator(doc)

        doc.setdefault(ITEM_STATE, CONTENT_STATE.DRAFT)

        if not doc.get('ingest_provider'):
            doc['source'] = app.config.get('DEFAULT_SOURCE_VALUE_FOR_MANUAL_ARTICLES')

        copy_metadata_from_user_preferences(doc)

    def get_file_from_document(self, doc):
        file = doc.get('media_fetched')
        if file:
            del doc['media_fetched']
        else:
            content = doc['media']
            res = process_file_from_stream(content, content_type=content.mimetype)
            file_name, content_type, metadata = res
            logger.debug('Going to save media file with %s ' % file_name)
            content.seek(0)
            with timer('media:put.original'):
                doc['media'] = app.media.put(content, filename=file_name, content_type=content_type, metadata=metadata)
            return content, content_type, decode_metadata(metadata)

        return file, file.content_type, file.metadata

    def upload_file_to_video_server(self, doc):
        """
        Upload file to video server and create rendition for it
        :param doc: info of file
        :return:
        """
        # upload video to video server
        res = self.video_editor.create(doc.get('media'))
        doc['media'] = res['_id']
        metadata = res.get('metadata')
        # create renditions
        rend = {
            'href': res.get('url'),
            'video_editor_id': res.get('_id'),
            'mimetype': res.get('mime_type'),
            'version': res.get('version'),
        }
        renditions = {'original': rend}
        return res, renditions, metadata
