from manifest_edit.plugin.mpd import BasePlugin
from manifest_edit.plugin.mpd import UTCTiming
from manifest_edit import libfmp4
from datetime import datetime
from schema import Schema
from manifest_edit.context import Context


class Plugin(BasePlugin, UTCTiming):
    '''
    utc_add plugin.

    The purpose of this plugin is to add the "UTCTiming" element to a manifest,
    if not already present.

    For details on the "UTCTiming" element, see ISO/IEC 23009-1 5.3.1.2,
    5.3.1.3, 5.8.4.11 and 5.8.5.7.

    Several UTC Timing Scheme are possible, each requiring its own syntax for
    the value (see 5.8.5.7).

    You can specify the Scheme and Value that utc_add will add to the manifest
    by means of the .yaml pipeline configuration file.

    "Scheme" can be specified using one of the following strings, the plugin
    will take care of applying the correct SchemeUriId string:

    - ntp
    - sntp
    - http-head
    - http-xsdate
    - http-iso
    - http-ntp
    - direct

    Each scheme requires to specify a value using a specific syntax. This
    plugin makes no effort to check that the provided "Value" string respect
    the correct syntax. The provided Value string will be used "as is".

    Example of config file using the "urn:mpeg:dash:utc:ntp:2014" scheme:

    .. code-block:: yaml

        mpd:
        - manifest_edit.plugins.mpd.utc_add:
            ntp:
            https://time.akamai.com/?iso

    Limitations: only implemented for .mpd manifests
    '''

    _name = __name__

    def schema(self):
        return Schema(
            {
                (lambda k: k in UTCTiming.SUPPORTED_UTC_SCHEMES): str
            }
        )

    def _appendIfNotExistsIdentical(self, manifest, descriptor):
        if descriptor not in manifest.utcTimings:
            manifest.utcTimings.append(descriptor)
        else:
            Context.log_warning('The current manifest already has an '
                                'UTCTiming element {}'.
                                format(descriptor)
                                )

    def add(self, manifest, storage):
        for scheme, value in self.config(storage=storage).items():
            if scheme == 'direct':
                # Adding UTC time, using the format specified in
                #  5.8.5.7 DIRECT-VALUE
                d = datetime.utcnow()
                direct_value = d.strftime('%Y-%m-%dT%H:%M:%SZ')
                self._appendIfNotExistsIdentical(
                    manifest,
                    libfmp4.mpd.Descriptor(
                        self.SUPPORTED_UTC_SCHEMES[scheme], direct_value
                    )
                )
            else:
                self._appendIfNotExistsIdentical(
                    manifest,
                    libfmp4.mpd.Descriptor(
                        self.SUPPORTED_UTC_SCHEMES[scheme], value
                    )
                )

    def process(self, manifest, storage):
        Context.log_warning(
            'The "utc_add" plugin is being deprecated in favour '
            'of the more generic "descriptor_add". Refer to the documentation '
            'and to the included example yaml config to learn how to migrate. '
            'This plugin may be removed in future version of Manifest Edit.'
            )
        self.add(manifest, storage)
