

import errno
import os
from subprocess import PIPE, Popen

import caffe2.python._import_c_extension as C
from caffe2.proto import caffe2_pb2
from caffe2.python import core


class NNModule:
    def __init__(self, net=None, device_map=None):
        if net is not None:
            serialized_proto = None
            if isinstance(net, core.Net):
                serialized_proto = net.Proto().SerializeToString()
            elif isinstance(net, caffe2_pb2.NetDef):
                serialized_proto = net.SerializeToString()

            # Distributed
            if device_map is not None:
                serialized_device_map = {}
                for k in device_map:
                    serialized_device_map[k] = device_map[k].SerializeToString()
                self._NNModule = C.NNModuleFromProtobufDistributed(
                    serialized_proto, serialized_device_map
                )
            # Default
            elif serialized_proto:
                self._NNModule, self._OpList = C.NNModuleFromProtobuf(serialized_proto)
            else:
                raise Exception(
                    "NNModule can be constructed with core.Net or caffe2_pb2.NetDef types"
                )
        else:
            self._NNModule = C.NNModule()

    @property
    def dataFlow(self):
        return self._NNModule.dataFlow()

    @property
    def controlFlow(self):
        return self._NNModule.getExecutionOrder()

    @property
    def nodes(self):
        return self._NNModule.dataFlow().nodes

    @property
    def operators(self):
        return self._NNModule.dataFlow().operators

    @property
    def tensors(self):
        return self._NNModule.dataFlow().tensors

    def createNode(self, val):
        return self._NNModule.dataFlow().createNode(val)

    def deleteNode(self, node):
        return self._NNModule.dataFlow().deleteNode(node)

    def createEdge(self, a, b):
        return self._NNModule.dataFlow().createEdge(a, b)

    def deleteEdge(self, a, b=None):
        if b:
            self._NNModule.dataFlow().deleteEdge(a, b)
        else:
            self._NNModule.dataFlow().deleteEdge(a)

    def replaceNode(self, old_node, new_node):
        return self._NNModule.dataFlow().replaceNode(old_node, new_node)

    def replaceProducer(self, tensor, new_producer):
        C.replaceProducer(tensor, new_producer)

    def replaceAllUsesWith(self, old_tensor, new_tensor):
        C.replaceAllUsesWith(old_tensor, new_tensor)

    def replaceAsConsumer(self, old_consumer, new_consumer):
        C.replaceAsConsumer(old_consumer, new_consumer)

    def replaceSubgraph(self, subgraph, new_node, inputs, outputs):
        self._NNModule.replaceSubgraph(subgraph, new_node, inputs, outputs)

    def deleteSubgraph(self, subgraph):
        self._NNModule.deleteSubgraph(subgraph)

    def createUniqueDataNode(self, prefix="_unique"):
        return self._NNModule.createUniqueDataNode(prefix)

    def convertToCaffe2Proto(self, old_proto=None):
        if not old_proto:
            old_proto = caffe2_pb2.NetDef()
        output = self._NNModule.convertToCaffe2Proto(old_proto)
        new_proto = caffe2_pb2.NetDef()
        new_proto.ParseFromString(output)
        return new_proto

    def match(self, pattern):
        for n in self.dataFlow.getMutableNodes():
            m = C.matchSubgraph(n, pattern)
            if m:
                yield m


def render(s):
    s = str(s)
    cmd_exists = lambda x: any(
        os.access(os.path.join(path, x), os.X_OK)
        for path in os.getenv("PATH", "").split(os.pathsep)
    )
    if cmd_exists("graph-easy"):
        p = Popen("graph-easy", stdin=PIPE)
        try:
            p.stdin.write(s.encode("utf-8"))
        except IOError as e:
            if e.errno == errno.EPIPE or e.errno == errno.EINVAL:
                pass
            else:
                # Raise any other error.
                raise

        p.stdin.close()
        p.wait()
    else:
        print(s)


NeuralNetOperator = C.NeuralNetOperator
Operator = C.NeuralNetOperator
NeuralNetData = C.NeuralNetData
Data = C.NeuralNetData
NNSubgraph = C.NNSubgraph
NNMatchGraph = C.NNMatchGraph
Graph = C.Graph
Annotation = C.Annotation
