1# -*- coding: utf-8 -*-
2from __future__ import unicode_literals
3
4import traceback
5
6from . import OrderedDict, __version__
7from .config import Config
8from .providers import (
9    EnzymeProvider,
10    FFmpegProvider,
11#    MediaInfoProvider,
12)
13
14_provider_map = OrderedDict([
15#    ('mediainfo', MediaInfoProvider),
16    ('ffmpeg', FFmpegProvider),
17    ('enzyme', EnzymeProvider)
18])
19
20provider_names = _provider_map.keys()
21
22available_providers = OrderedDict([])
23
24
25class KnowitException(Exception):
26    """Exception raised when knowit fails to perform media info extraction because of an internal error."""
27
28
29def initialize(context=None):
30    """Initialize knowit."""
31    if not available_providers:
32        context = context or {}
33        config = Config.build(context.get('config'))
34        for name, provider_cls in _provider_map.items():
35            available_providers[name] = provider_cls(config, context.get(name) or config.general.get(name))
36
37
38def know(video_path, context=None):
39    """Return a dict containing the video metadata.
40
41    :param video_path:
42    :type video_path: string
43    :param context:
44    :type context: dict
45    :return:
46    :rtype: dict
47    """
48    try:
49        # handle path-like objects
50        video_path = video_path.__fspath__()
51    except AttributeError:
52        pass
53
54    try:
55        context = context or {}
56        context.setdefault('profile', 'default')
57        initialize(context)
58
59        for name, provider in available_providers.items():
60            if name != (context.get('provider') or name):
61                continue
62
63            if provider.accepts(video_path):
64                result = provider.describe(video_path, context)
65                if result:
66                    return result
67
68        return {}
69    except Exception:
70        raise KnowitException(debug_info(context=context, exc_info=True))
71
72
73def dependencies(context=None):
74    """Return all dependencies detected by knowit."""
75    deps = OrderedDict([])
76    try:
77        initialize(context)
78        for name, provider_cls in _provider_map.items():
79            if name in available_providers:
80                deps[name] = available_providers[name].version
81            else:
82                deps[name] = {}
83    except Exception:
84        pass
85
86    return deps
87
88
89def _centered(value):
90    value = value[-52:]
91    return '| {msg:^53} |'.format(msg=value)
92
93
94def debug_info(context=None, exc_info=False):
95    lines = [
96        '+-------------------------------------------------------+',
97        _centered('KnowIt {0}'.format(__version__)),
98        '+-------------------------------------------------------+'
99    ]
100
101    first = True
102    for key, info in dependencies(context).items():
103        if not first:
104            lines.append(_centered(''))
105        first = False
106
107        for k, v in info.items():
108            lines.append(_centered(k))
109            lines.append(_centered(v))
110
111    if context:
112        debug_data = context.pop('debug_data', None)
113
114        lines.append('+-------------------------------------------------------+')
115        for k, v in context.items():
116            if v:
117                lines.append(_centered('{}: {}'.format(k, v)))
118
119        if debug_data:
120            lines.append('+-------------------------------------------------------+')
121            lines.append(debug_data())
122
123    if exc_info:
124        lines.append('+-------------------------------------------------------+')
125        lines.append(traceback.format_exc())
126
127    lines.append('+-------------------------------------------------------+')
128    lines.append(_centered('Please report any bug or feature request at'))
129    lines.append(_centered('https://github.com/ratoaq2/knowit/issues.'))
130    lines.append('+-------------------------------------------------------+')
131
132    return '\n'.join(lines)
133