"""Metadata transport composition. 명시 설정 전에는 생성/접속/기동하지 않는다."""
import os
from urllib.parse import urlsplit

from app.metadata_publisher import MetadataPublisher, MetadataSettings


def publisher_from_environment(environ=None):
    env = os.environ if environ is None else environ
    enabled = env.get('CONTEXTRA_METADATA_ENABLED', 'false')
    if enabled not in ('true', 'false'):
        raise ValueError('Invalid metadata enable setting.')
    if enabled == 'false':
        return None
    url = env.get('CONTEXTRA_METADATA_REDIS_URL', '')
    try:
        parsed = urlsplit(url)
        valid = (parsed.scheme in ('redis', 'rediss') and parsed.hostname and parsed.password
                 and (parsed.port is None or 1 <= parsed.port <= 65535))
    except ValueError:
        valid = False
    if not valid:
        raise ValueError('Authenticated metadata Redis configuration is required.')
    options = {}
    for name in ('workers', 'active_worker_limit', 'max_channels', 'max_bytes', 'max_message_bytes', 'stream_length', 'stream_ttl',
                 'max_age', 'io_timeout'):
        value = env.get('CONTEXTRA_METADATA_' + name.upper())
        if value is not None:
            try:
                options[name] = float(value) if name in ('max_age', 'io_timeout') else int(value)
            except ValueError:
                raise ValueError('Invalid metadata resource setting.') from None
    options['namespace'] = env.get('CONTEXTRA_METADATA_NAMESPACE', 'contextra:metadata:v1')
    options['worker_mode'] = env.get('CONTEXTRA_METADATA_WORKER_MODE', 'fixed')
    settings = MetadataSettings(url, **options)
    if env.get('CONTEXTRA_STREAM_EXECUTION_MODE', 'thread') == 'process':
        from app.process_metadata import ProcessMetadataControl
        return ProcessMetadataControl(settings)
    if settings.worker_mode == 'channel':
        from app.channel_publisher import ChannelMetadataPublisher
        return ChannelMetadataPublisher(settings)
    return MetadataPublisher(settings)
