from .ref import Ref, refjoin

class NotFound(Exception): pass


class Viewable:
    def __init__(self, ref):
        self.ref = Ref(ref)
        assert(self.TYPENAME == ref.typename,
               'Cannot load "{}" as {}'.format(ref, self.__class__.__name__))

    @classmethod
    def load(cls, db, ref):
        raise NotImplementedError('Cannot load an abstract Viewable.')

    def view(self, viewer):
        raise NotImplementedError('Cannot view an abstract Viewable.')

def extra_ref_components(*args):
    def add_ref_components(cls):
        cls.REF_COMPONENTS = {args[i]: i+1 for i in range(len(args))}  # 0 is type
        return cls
    return add_ref_components


class VersionedMixin:
    def __init__(self, ref):
        super(VersionedMixin, self).__init__(ref)
        self.version = None
        if len(self.ref) > self.REF_COMPONENTS['version']:
            self.version = self.ref[self.REF_INDEX_VERSION]
        self.resolved_version = self.version

    def resolve_version(self, db, ref):
        if self.resolved_version is None:
            self.resolved_version = db.get(self.ref)
            print('VersionedMixin: resolving version:', self.ref, '->', self.resolved_version)

    @property
    def resolved_ref(self):
        return refjoin(self.ref, [self.resolved_version])

    @classmethod
    def load_versioned_with_op(cls, db, ref, load_op):
        x = cls(ref)
        x.resolve_version(db, ref)
        if not x.resolved_version: raise NotFound
        print('loading from DB:', x.resolved_ref)
        x.data = load_op(x.resolved_ref)
        if not x.data: raise NotFound
        return x

    def view(self, viewer):
        """May only be called after `load()`."""
        if self.version == self.resolved_version:
            return viewer.OK(self)
        else:
            return viewer.Alias(self.resolved_ref)


type_map = {}

def typename(typename):
    def typed(cls):
        cls.TYPENAME = typename
        type_map[typename] = cls
        return cls
    return typed

@@ -145,17 +145,17 @@
   assert
-(
+ 
 self.TYP
@@ -176,16 +176,18 @@
 ypename,
+ %5C
 %0A       
@@ -255,17 +255,16 @@
 _name__)
-)
 %0A%0A    @c
@@ -911,22 +911,71 @@
 REF_
-INDEX_VERSION%5D
+COMPONENTS%5B'version'%5D%5D%0A            self.resolved_ref = self.ref
 %0A   
@@ -1168,52 +1168,36 @@
     
-print('VersionedMixin: resolving version:', 
+self.resolved_ref = refjoin(
 self
@@ -1206,14 +1206,9 @@
 ef, 
-'-%3E', 
+%5B
 self
@@ -1228,76 +1228,66 @@
 sion
+%5D
 )
-%0A
 %0A    
-@property%0A    def resolved_ref(self):%0A        return refjoin(
+        print('VersionedMixin: resolved version:', 
 self
@@ -1284,33 +1284,38 @@
 on:', self.ref, 
-%5B
+'-%3E', 
 self.resolved_ve
@@ -1319,17 +1319,16 @@
 _version
-%5D
 )%0A%0A    @

fix some very stupid bugs (what was I drinking...?)