from .common import ModelException
import sympy


class Model(object):
    def __init__(self, **entities):
        self.entities = entities
        self.restrictions = list()

    def restricted_by(self, *args):
        self.restrictions.extend(args)
        return self

    def build(self):
        self._validate()
        return FrozenModel(self.entities, self.restrictions)

    def _validate(self):
        variables = dict()
        conditions = list()
        used_variabled = list()
        for name, params in self.entities.iteritems():
            for param_name, param in params.iteritems():
                full_name = '.'.join([name, param_name])
                param_type = param[0]
                param_var = sympy.symbols(full_name + '.type')
                variables[full_name] = {'type': (param_var, param_type)}
                constraints = param[2]
                for k, v in constraints.iteritems():
                    var = sympy.symbols('.'.join([full_name, k]))
                    variables[full_name][k] = (var, v)
                    conditions.append(var - v)
                    used_variabled.append(var)
        for first, second in self.restrictions:
            first_var, first_type = variables[first]['type']
            second_var, second_type = variables[second]['type']
            first_len, second_len = sympy.symbols(' '.join([first + '.length', second + '.length']))
            conditions.extend([first_var - first_type,
                               second_var - second_type,
                               first_var - second_var,
                               first_len - second_len])
            used_variabled.extend([first_var, second_var])
        if conditions:
            ok = sympy.solve(conditions, used_variabled)
            if not ok:
                raise ModelException()


class FrozenModel(object):
    def __init__(self, entities, restrictions):
        self.entities = entities
        self.restrictions = {v:k for (k, v) in restrictions}

    def create(self):
        ready_values = dict()
        result = list()
        for name, params in self.entities.iteritems():
            for param_name, param in params.iteritems():
                full_name = '.'.join([name, param_name])
                ready_values[full_name] = param[1]()
        for name, params in self.entities.iteritems():
            resolved_params = dict()
            for param_name in params.keys():
                full_name = '.'.join([name, param_name])
                if full_name in self.restrictions:
                    full_name = self.restrictions[full_name]
                resolved_params[param_name] = ready_values[full_name]
            result.append((name, resolved_params))
        return result

@@ -828,16 +828,123 @@
 _type)%7D%0A
+                conditions.append(param_var - param_type)%0A                used_variabled.append(param_var)%0A
         
@@ -974,16 +974,16 @@
 aram%5B2%5D%0A
-
         
@@ -1307,93 +1307,54 @@
    f
-irst_var, first_type = variables%5Bfirst%5D%5B'type'%5D%0A            second_var, second_type =
+or key in %5Bk for k in variables%5Bfirst%5D if k in
  var
@@ -1371,16 +1371,10 @@
 ond%5D
-%5B'type'
 %5D
+:
 %0A   
@@ -1386,355 +1386,138 @@
     
-first_len, second_len = sympy.symbols(' '.join(%5Bfirst + '.length', second + '.length'%5D))%0A            conditions.extend(%5Bfirst_var - first_type,%0A                               second_var - second_type,%0A                               first_var - second_var,%0A                               first_len - second_len%5D)%0A            used_variabled.ext
+    first_var = variables%5Bfirst%5D%5Bkey%5D%5B0%5D%0A                second_var = variables%5Bsecond%5D%5Bkey%5D%5B0%5D%0A                conditions.app
 end(
-%5B
 firs
@@ -1521,17 +1521,18 @@
 irst_var
-,
+ -
  second_
@@ -1534,17 +1534,16 @@
 cond_var
-%5D
 )%0A      

remove knowledge about 'length' from model (2/2)