#!/usr/bin/python2
# https://stevenloria.com/lazy-properties/

from __future__ import print_function
from threading import Lock
from functools import partial
from univention.config_registry import ConfigRegistry
import inspect


def lazy(cls):
    """
    Copy methods and constants from UCR and wrap for lazy loading.
    """
    for name, value in inspect.getmembers(ConfigRegistry):
        if hasattr(cls, name):
            continue

        if callable(value):
            def wrap(__meth, *args, **kwargs):
                if not isinstance(cls._instance, ConfigRegistry):
                    with cls._lock:
                        print("UCR.init")
                        ucr = ConfigRegistry()
                        ucr.load()
                        if not isinstance(cls._instance, ConfigRegistry):
                            cls._instance = ucr
                            # undo proxying
                            for name2, value2 in inspect.getmembers(ConfigRegistry, callable):
                                if isinstance(getattr(cls, name2), partial):
                                    print("UNPROXY", name2, getattr(cls, name2), value2)
                                    setattr(cls, name2, partial(value2, cls._instance))

                assert isinstance(cls._instance, ConfigRegistry)

                print("PROXY", __meth, *args, **kwargs)
                return __meth(cls._instance, *args, **kwargs)

            setattr(cls, name, partial(wrap, value))
        else:
            setattr(cls, name, value)

    return cls


@lazy
class LazyUcr(object):
    _instance = None
    _lock = Lock()

    def __new__(cls):
        """Singleton"""
        print("Lazy.init")
        if cls._instance is None:
            with cls._lock:
                if cls._instance is None:
                    cls._instance = super(LazyUcr, cls).__new__(cls)
        return cls._instance


ucr = LazyUcr()  # type: ConfigRegistry
print()
print(ucr.PREFIX)
print()
print(ucr.values()[:2])
print()
print(ucr["server/role"])
print(ucr["server/role"])
