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


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

    The purpose of this plugin is to remove the "UTCTiming" element from a
    manifest, if 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 choose to remove only those UTCTiming elements having a specific
    Scheme and Value by means of the .yaml configuration file.

    "Scheme" can be specified using one of the following strings:

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

    Additionally, you can decide to just remove the UTCTiming element, whatever
    scheme it may have. This is done by specifying the value

    .. code-block:: yaml

      - '*'

    Example of configuration file removing only UTCTiming elements having the
    "urn:mpeg:dash:utc:ntp:2014" scheme:

    .. code-block:: yaml

      mpd:
      - manifest_edit.plugins.mpd.utc_remove:
        - 'ntp':

    Example of configuration file removing any possible UTCTiming elements:

    .. code-block:: yaml

      mpd:
      - manifest_edit.plugins.mpd.utc_remove:
        - '*':
    '''

    _name = __name__

    def schema(self):
        return Schema(
            [
                Or(lambda k: k in UTCTiming.SUPPORTED_UTC_SCHEMES, '*')
            ]
        )

    def remove(self, manifest, storage):
        # remove only works on manifests that do have an UTCTiming tag
        if not len(manifest.utcTimings):
            Context.log_warning('Trying to remove UTCTiming element from a '
                                ' manifest that does not contain one.'
                                )
            return
        # Not the most efficient way to do it but until we find a way to avoid
        # copying STL containers back and forth it's just the way it is
        for scheme_to_remove in self.config(storage=storage):
            if scheme_to_remove == '*':
                manifest.utcTimings.clear()
                break
            else:
                scheme_id_uri_to_remove = self.SUPPORTED_UTC_SCHEMES[
                    scheme_to_remove
                ]
                for descriptor in manifest.utcTimings:
                    manifest.utcTimings = libfmp4.mpd.Descriptors([
                        timing for timing in manifest.utcTimings if
                        descriptor.schemeIdUri != scheme_id_uri_to_remove
                    ])

    def process(self, manifest, storage):
        Context.log_warning(
            'Warning: the "utc_remove" plugin is being deprecated in favour '
            'of the more generic "descriptor_remove". 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.remove(manifest, storage)
