# -*- coding: utf-8 -*-
#
# Copyright 2013 Will Barton. 
# All rights reserved.
# 
# Redistribution and use in source and binary forms, with or without 
# modification, are permitted provided that the following conditions
# are met:
# 
#   1. Redistributions of source code must retain the above copyright 
#      notice, this list of conditions and the following disclaimer.
#   2. Redistributions in binary form must reproduce the above copyright 
#      notice, this list of conditions and the following disclaimer in the 
#      documentation and/or other materials provided with the distribution.
#   3. The name of the author may not be used to endorse or promote products
#      derived from this software without specific prior written permission.
# 
# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
# AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
# THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
""" 
Implementation of a NetworkX-compatible Graph class that stores
verticies and edges with the SQLAlchemy ORM.
"""

from percival.errors import PercivalGraphError, PercivalGraphConsistencyError

import itertools

class SQLAlchemyGraphStorage(object):

    def __init__(self, redis, label=u"no_label", **kwargs):
        self._redis = redis
        self._label = label

    ### Main API

    def _graph_attributes(self):
        """ 
        Returns a dictionary-like object containing graph attributes
        """
        raise NotImplementedError

    def _node_attributes(self, n):
        """ 
        Returns a dictionary-like object containing attributes for the
        given node.
        """
        raise NotImplementedError

    def _edge_attributes(self, u, v):
        """ 
        Returns a dictionary-like object containing attributes for the
        given edge.
        """
        raise NotImplementedError
    
    def _nodes(self):
        """
        This generator yields tuples containing (node label, node
        attributes) for every node in the graph.
        """
        raise NotImplementedError

    def _edges(self):
        """
        This generator yields tuples containing (node label, node label,
        edge attributes) for every pair of nodes that share an edge in
        the graph.
        """
        raise NotImplementedError

    def _adjacents(self, n=None, bidirectional=True, reverse=False):
        """
        This generator yields, alternatively, tuples containing (node
        label, list of adjacent nodes and edge attributes) for every
        node in the graph, or, if n is given, tuples of (adjacent node,
        edge attributes) for all nodes n shares an edge with.
        """
        raise NotImplementedError

    ### Adding/Removing Nodes and Edges

    def _add_node(self, n, **kwargs):
        raise NotImplementedError

    def _remove_node(self, n):
        raise NotImplementedError

    def _add_edge(self, u, v, bidirectional=True, **kwargs):
        raise NotImplementedError

    def _remove_edge(self, u, v):
        raise NotImplementedError

    def _clear(self):
        raise NotImplementedError


