import logging
from werkzeug.datastructures import MultiDict

from aleph import authz
from aleph.graph.schema import NodeType

log = logging.getLogger(__name__)


class GraphQuery(object):

    def __init__(self, graph, items):
        self.graph = graph
        self.data = MultiDict(items)

    @property
    def limit(self):
        try:
            return min(int(self.data.get('limit', 15)), 5000)
        except:
            return 15

    @property
    def offset(self):
        try:
            return max(int(self.data.get('offset', 0)), 0)
        except:
            return 0

    def _as_json(self, results):
        """Helper to make query responses more uniform."""
        return {
            'status': 'ok',
            'limit': self.limit,
            'offset': self.offset,
            'results': results
        }


class NodeQuery(GraphQuery):

    def text(self):
        text = self.data.get('text')
        if text is not None:
            text = unicode(text).strip()
            if len(text) < 1:
                text = None
            else:
                text = '(?i).*%s.*' % text
        return text

    def collection_id(self):
        acl = authz.collections(authz.READ)
        collections = []
        for coll in self.data.getlist('collection_id'):
            coll = int(coll)
            if coll in acl:
                collections.append(coll)
        return collections or acl

    def query(self):
        args = {
            'acl': authz.collections(authz.READ),
            'limit': self.limit,
            'offset': self.offset,
            'text': self.text(),
            # 'collection_id': self.collection_id()
        }
        filters = []
        filters.append('nodeColl.alephCollection IN {acl}')
        filters.append('otherColl.alephCollection IN {acl}')
        if args['text'] is not None:
            filters.append('node.name =~ {text}')

        q = "MATCH (node)-[:PART_OF]->(nodeColl:Collection) " \
            "MATCH (node)-[r]-(other) " \
            "MATCH (p)-[:PART_OF]->(otherColl:Collection) " \
            "WHERE %s " \
            "WITH node, count(r) AS degree " \
            "ORDER BY degree DESC " \
            "SKIP {offset} LIMIT {limit} " \
            "RETURN node, degree "
        q = q % ' AND '.join(filters)
        # print args
        return q, args

    def execute(self):
        query, args = self.query()
        nodes = []
        for row in self.graph.run(query, **args):
            node = NodeType.dict(row.get('node'))
            node['$degree'] = row.get('degree')
            nodes.append(node)
        return nodes

    def to_dict(self):
        return self._as_json(self.execute())


class EdgeQuery(GraphQuery):

    def to_dict(self):
        return self._as_json([], [])

@@ -1613,18 +1613,16 @@
         
- #
  'collec
@@ -1708,20 +1708,17 @@
 ppend('n
-odeC
+c
 oll.alep
@@ -1725,35 +1725,45 @@
 hCollection IN %7B
-acl
+collection_id
 %7D')%0A        filt
@@ -1775,21 +1775,17 @@
 ppend('o
-therC
+c
 oll.alep
@@ -1939,12 +1939,9 @@
 -%3E(n
-odeC
+c
 oll:
@@ -2039,13 +2039,9 @@
 -%3E(o
-therC
+c
 oll:

Allow filtering by collection.