## @package net_builder
# Module caffe2.python.net_builder
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from caffe2.python import core, context
from caffe2.python.task import Task, TaskGroup
from caffe2.python.control_ops_util import add_if_op, add_while_op


@context.define_context()
class NetBuilder(object):
    """
    Scope-driven mechanism for building nets, loops and conditional blocks.
    Arguments:
      name: NetBuilder's name
      initial_scope: list of blobs that are available for reading/writing
    Example:
        from caffe2.python.net_builder import NetBuilder, ops
        with NetBuilder() as nb:
            c = ops.Const(5)
            d = ops.Const(0)
            with ops.loop():
                ops.stop_if(ops.LE([c, ops.Const(0)]))
                ops.Add([c, ops.Const(-1)], [c])
                with ops.If(ops.GE([c, ops.Const(3)])):
                    ops.Add([d, ops.Const(10)])
            ops.Print(c, [])
            ops.Print(d, [])
        step = core.to_execution_step(nb)
    """
    def __init__(self, name=None, initial_scope=None, _stop_blob_required=False,
                 _stop_blob=None, _fullname=None, _use_control_ops=False):
        parent = NetBuilder.current(required=False)
        assert not _fullname or not name, 'Cannot set both _fullname and name'
        assert not _use_control_ops or \
            (not _stop_blob_required and not _stop_blob), \
            'Stop blobs are not used with control operators'
        self.name = _fullname or '/'.join(
            n for n in (parent.name if parent else None, name) if n
        )
        self._frozen = False
        self._current_net = None
        self._children = []
        if parent:
            # make sure parent has an up to date lexical scope computed
            parent._update_lexical_scope()
        self._init_lexical_scope = set(parent._lexical_scope) if parent else set()
        if initial_scope:
            self._init_lexical_scope |= set([str(b) for b in initial_scope])
        self._lexical_scope = set(self._init_lexical_scope)
        self._stop_blob = _stop_blob
        self._stop_blob_required = _stop_blob_required
        self._use_control_ops = _use_control_ops

    def stop_blob(self):
        """
        Returns the BlobReference to the stop_blob of this NetBuilder.
        If one is not yet available, creates one.
        This function assumes that the stop_blob() will be used immediatelly
        in the current net, so it doesn't initialize it if the current net is
        the first of the builder.
        """
        assert not self._use_control_ops, \
            'Stop blobs are not used with control operators'
        if self._stop_blob is None:
            net = self.current_net()
            self._stop_blob = core.BlobReference(
                net.NextName('stop_blob'), net=net)
            if self._current_net != self._children[0]:
                self._children.insert(0, core.Net('stop_blob_init'))
                self._children[0].Const(False, blob_out=self._stop_blob)
        return self._stop_blob

    def stop_if(self, blob):
        assert not self._use_control_ops, \
            'Stop blobs are not used with control operators'
        ops.Copy(blob, self.stop_blob())
        self._current_net = None

    def _assert_mutable(self):
        assert not self._frozen, (
            'This NetBuilder (%s) has been built already.' % self.name)

    def _update_lexical_scope(self):
        """
        Updates lexical scope based on the current list of children.
        Lexical scope contains names of blobs that are currently available
        and were introduced in the net builder
        """
        self._lexical_scope = set(self._init_lexical_scope)
        for child in self._children:
            if isinstance(child, core.Net):
                self._lexical_scope |= child.UsedBlobNames()
            elif isinstance(child, NetBuilder) and child._use_control_ops:
                self._lexical_scope |= child._lexical_scope

    def _reset_children(self):
        self._current_net = None
        self._children = []
        self._lexical_scope = set(self._init_lexical_scope)

    def add(self, child):
        self._assert_mutable()

        if self._use_control_ops:
            assert isinstance(child, core.Net) or (
                isinstance(child, NetBuilder) and child._use_control_ops), \
                "Expected Net or NetBuilder with control ops"

        self._current_net = None
        self._children.append(child)
        # to-do : check it's not a dag net
        if isinstance(child, core.Net):
            self._current_net = child
        self._update_lexical_scope()
        return child

    def current_net(self, name=None):
        self._assert_mutable()
        if self._current_net is None or name is not None:
            self.add(core.Net(name))
        return self._current_net

    def freeze(self):
        for child in self._children:
            if hasattr(child, 'freeze'):
                child.freeze()
        self._current_net = None
        self._frozen = True

    def get(self):
        self.freeze()
        return self._children

    def __exit__(self, etype, *args):
        if self._use_control_ops and len(self._children) > 0:
            _children = self._children
            self._reset_children()
            merged_net = NetBuilder.merge_nets(
                _children, self._lexical_scope)
            assert merged_net, "Expected a non-empty merge of children"
            self._children = [merged_net]

        self.freeze()
        if etype is not None:
            return
        assert (not self._stop_blob_required) or self._stop_blob is not None, (
            'This NetBuilder (%s) requires a stop condition ' % self.name +
            'to be set with `stop` or `stop_if`')

    @staticmethod
    def merge_nets(nets_or_builders, outer_blob_names):
        # Only nets or builders with control ops are allowed.
        # Need to pay attention to external outputs, e.g.
        #   ...
        #   IfNet1 (cond_blob):
        #       (Net1)
        #           X = 1
        #       IfNet2 (...):
        #           X = X + 1
        #   ...
        # In this example there're two children in then branch of IfNet1:
        # a subnet Net1 that creates blob X and sets its value to one, and
        # a net builder IfNet2 that (conditionally) increments X.
        # From IfNet2's point of view X is an external input
        # and output blob, it will be put into IfNet2 net's external_output.
        # At the same time, from the point of view of IfNet1 X is purely local.
        # Net.AppendNet just merges external outputs of the networks, so
        # without checking this the result of Net1.AppendNet(IfNet2's net)
        # would have blob X in external_output

        net = None
        for n in nets_or_builders:
            cur = None
            if isinstance(n, NetBuilder):
                assert n._use_control_ops, \
                    "Merging of NetBuilder supported only for control ops"
                nets = n.get()
                assert len(nets) == 1 and isinstance(nets[0], core.Net), \
                    "Invalid control op net builder"
                cur = nets[0]
            else:
                assert isinstance(n, core.Net)
                cur = n
            if net:
                net.AppendNet(cur)
            else:
                net = cur
        if net:
            # correct external output
            external_outputs = [o for o in net.Proto().external_output
                                    if o in outer_blob_names]
            net.Proto().external_output[:] = external_outputs
        return net

    def __str__(self):
        return self.name or 'Un-named NetBuilder'


class Operations(object):
    """
    Operations to be used in the context of a NetBuilder.
    """
    def net(self, net=None, name=None):
        """
        Retrieves the current net, or add a new net to the builder.
        Args:
            net:   If provided, add the given net to the active builder.
                   Else, returns the current Net or creates a new one as needed.
            name:  if provided, creates a new Net with given name and makes
                   it the new current net of the active builder. Cannot
                   be provided if net is provided.
        """
        assert name is None or net is None, (
            'Cannot provide both `net` and `name`.')
        if net is not None:
            NetBuilder.current().add(net)
            return net
        return NetBuilder.current().current_net(name=name)

    def __getattr__(self, op_type):
        """
        Adds an operator call to the currently active Net.
        """
        if op_type.startswith('__'):
            raise AttributeError()
        # We want hasattr to work properly even if no context is active.
        if NetBuilder.current(required=False) is None:
            raise AttributeError('No active NetBuilder.')
        return getattr(self.net(), op_type)

    def task_group(self):
        """
        Creates a local task group which will execute as the next step of
        the current NetBuilder.
        """
        from caffe2.python import task
        group = NetBuilder.current()
        with task.Cluster():
            with task.Node('local'):
                tg = task.TaskGroup()
                group.add(tg)
                return tg

    def stop(self):
        """
        Stop execution of the current execution step.
            Example:
                ops.Print(a, 0)
                ops.stop()
                ops.Print(b, 0)
            In the example, 'b' will never be printed.
        """
        return self.stop_if(ops.Const(True))

    def stop_if(self, blob):
        """
        Stop execution of the current execution step if the
        condition `blob` is met.
            Example:
                ops.Print(a, 0)
                ops.stop_if(ops.LE([x, ops.Const(0)]))
                ops.Print(b, 0)
            In the example, 'b' will only be printed if the value of scalar
            tensor 'x' lower or equal to 0.
        """
        return NetBuilder.current().stop_if(blob)

    def loop(self, iters=None, name=None):
        """
        Creates a NetBuilder that will execute in a loop as the next step of
        the current NetBuilder. If `iters` is provided, the loop will execute
        for `iters` iterations and then stop. `iters` can be a constant or a
        BlobReference. If `iters` is not provided, the loop will execute
        until `ops.stop` or `ops.stop_if` is called.
            Examples:
                a = ops.Const(5)
                with ops.loop():
                    ops.stop_if(ops.LE([a, ops.Const(0)]))
                    ops.Print(a, 0)
                    ops.Add([a, ops.Const(-1)], [a])
            Above, 'a' will be printed 5 times, with values 5 to 1.

                with ops.loop(10) as loop:
                    ops.LogInfo(loop.iter())
            This will print the numbers from 0 to 9.

                x = ops.Add([ops.Const(10), ops.Const(10)])
                with ops.loop(x) as loop:
                    ops.LogInfo(loop.iter())
            This will print the numbers from 0 to 19.
        """
        return NetBuilder.current().add(_Loop(iters, name=name))

    def stop_guard(self, has_stopped_blob=None, name=None):
        """
        Creates a NetBuilder that will execute once as the next step of the
        current NetBuilder. After execution, a bool tensor will indicate
        whether the inner execution was halted with `stop` or `stop_if`.
            Example:
                a = ops.Const(True)
                with ops.stop_guard() as sg1:
                    ops.stop_if(a)
                    ops.Print(ops.Const('did not stop'))
                b = ops.Const(False)
                with ops.stop_guard() as sg2:
                    ops.stop_if(b)
                    ops.Print(ops.Const('did not stop'))
                ops.Print(sg1.has_stopped(), [])
                ops.Print(sg2.has_stopped(), [])
            In the example, 'did not stop' will be printed once,
            followed by True and False.
        """
        return NetBuilder.current().add(
            _StopGuard(has_stopped_blob=has_stopped_blob, name=name))

    def If(self, cond, name=None):
        """
        Creates a NetBuilder that will execute once as the next step of the
        current NetBuilder if the blob `cond` is True.
            Example:
                with ops.If(ops.Const(True)):
                    ops.Print(ops.Const('Will print'))
                with ops.If(ops.Const(False)):
                    ops.Print(ops.Const('Wont print'))
            The example will print 'Will print' once.
        """
        return NetBuilder.current().add(_RunIf(cond, name=name))

    def IfNet(self, cond, name=None):
        """
        Same as If, but uses 'If' operator instead of execution step logic
        """
        return NetBuilder.current().add(_RunIfNet(cond, name=name))

    def Else(self, name=None):
        """
        Else branch of IfNet, has to be specified immediately after IfNet.
            Example:
                with ops.IfNet(ops.LT([x, y])):
                    ...
                with ops.Else():
                    ...
        """
        return _RunElseNet(name=name)

    def WhileNet(self, name=None):
        """
        NetBuilder for 'While' control operator
        """
        return NetBuilder.current().add(_RunWhileNet(name=name))

    def Condition(self, name=None):
        """
        Loop's condition, executed within WhileNet context
        """
        assert isinstance(NetBuilder.current(), _RunWhileNet), \
            "Use of Condition outside of WhileNet"
        return _RunWhileCondition(name=name)

    def task_init(self):
        """
        Defines operations that will be executed once at task startup.
        Useful when implementing processors, that don't have access to the Task
        top-level structure.

        This setup will be run only once, even if multiple instances of the task
        will run in parallel. For instance-local initialization, use
        `task_instance_init` instead.

            Example:
                def my_processor(rec):
                    with ops.task_init():
                        one = ops.Const(1)
                        two = ops.Const(1)
                    return Tuple(
                        ops.Add(rec[0](), zero), ops.Add(rec[1](), two))
        """
        setup = _SetupBuilder(_SetupBuilder.INIT)
        self.net().add_attribute(Task.TASK_SETUP, setup)
        return setup

    def task_exit(self):
        """
        Define operations to be executed once at task shutdown.
        Useful when implementing processors, that don't have access to the Task
        top-level structure.

        This shutdown will be run only once, after all concurrent instances of
        the task have already finished. For instance-local shutdown,
        use `task_instance_exit` instead.

            Example:
                def read_queue(queue):
                    with ops.task_exit():
                        queue.close(ops.net())
                    return queue.read(ops.net())
        """
        setup = _SetupBuilder(_SetupBuilder.EXIT)
        self.net().add_attribute(Task.TASK_SETUP, setup)
        return setup

    def task_instance_init(self):
        """
        Defines operations that will be executed once at startup of each
        instance of a task. This can be seen as "thread_local" initialization.
        It is guaranteed to run only after all `task_init` logic finishes.

        This setup will be run concurrently for each instance of a task.
        For global task initialization, use `task_init` instead.
        """
        setup = _SetupBuilder(_SetupBuilder.INIT)
        self.net().add_attribute(Task.TASK_INSTANCE_SETUP, setup)
        return setup

    def task_instance_exit(self):
        """
        Defines operations that will be executed once at shutdown of each
        instance of a task. This can be seen as "thread_local" finalization.

        This shutdown will be run concurrently for each instance of a task.
        For global task shutdown, use `task_exit` instead.
        """
        setup = _SetupBuilder(_SetupBuilder.EXIT)
        self.net().add_attribute(Task.TASK_INSTANCE_SETUP, setup)
        return setup

    def local_init(self):
        """
        Similar to `task_init`, but executes at TaskGroup's startup instead,
        before any task of the group starts executing. This will run only
        once on each node, before initialization of any task, so it can be
        used e.g. to initialize blobs shared across tasks.
        """
        setup = _SetupBuilder(_SetupBuilder.INIT)
        self.net().add_attribute(TaskGroup.LOCAL_SETUP, setup)
        return setup

    def local_exit(self, name=None):
        """
        Similar to `task_exit`, but executes at TaskGroup's exit instead,
        after all tasks of the group finished execution.
        This will run only once on each node.
        """
        setup = _SetupBuilder(_SetupBuilder.EXIT, name)
        self.net().add_attribute(TaskGroup.LOCAL_SETUP, setup)
        return setup

    def task_reporter(self, interval_ms=1000, name=None):
        """
        Define operations to be executed at every time interval from
        task start-up to finish. These operations are guaranteed to
        execute at least once after all other operations of the task are
        finished.

            Example:
                with ops.task_reporter(interval_ms=10000):
                    ops.LogInfo('10s elapsed')
        """
        return _ReporterBuilder(interval_ms, net=self.net(), name=name)

    def local_reporter(self, interval_ms=1000, name=None):
        """
        Similar to task_report, but operations defined within this block
        will run repeatedly for as long as any of the tasks in the current
        TaskGroup have not finished.
        """
        return _ReporterBuilder(interval_ms, name=name)


ops = Operations()


class _ReporterBuilder(NetBuilder):
    def __init__(self, interval_ms, net=None, name=None):
        NetBuilder.__init__(self, name)
        self._net = net
        self.interval_ms = interval_ms

    def __exit__(self, etype, *args):
        if etype is None:
            step = core.to_execution_step(self)
            step.RunEveryMillis(self.interval_ms)
            if self._net:
                self._net.add_attribute(Task.REPORT_STEP, step)
            else:
                TaskGroup.current().report_step(
                    step, interval_ms=self.interval_ms)
        NetBuilder.__exit__(self, etype, *args)


class _SetupBuilder(NetBuilder):
    INIT = 'init'
    EXIT = 'exit'

    def __init__(self, type, name=None):
        NetBuilder.__init__(self, name)
        self.type = type

    def setup(self, net):
        if self.type == _SetupBuilder.INIT:
            return core.to_execution_step(self)

    def exit(self, net):
        if self.type == _SetupBuilder.EXIT:
            return core.to_execution_step(self)


class _RunOnce(NetBuilder):
    def __init__(self, name=None):
        NetBuilder.__init__(self, name)

    def __exit__(self, etype, *args):
        if etype is None and self._stop_blob is not None:
            ops.stop()
        NetBuilder.__exit__(self, etype, *args)


class _StopGuard(_RunOnce):
    def __init__(self, has_stopped_blob=None, name=None):
        _RunOnce.__init__(self, name)
        self._stopped = has_stopped_blob
        self._ran = False

    def __enter__(self):
        r = _RunOnce.__enter__(self)
        self._stopped = ops.Const(True, blob_out=self._stopped)
        return r

    def __exit__(self, etype, *args):
        if etype is None:
            self._ran = True
            ops.Const(False, blob_out=self._stopped)
        _RunOnce.__exit__(self, etype, *args)

    def has_stopped(self):
        """
        Return a blob that will be set to scalar bool `True` after
        this net builder ran, iff it was halted early.
        """
        assert self._ran, 'Context not used yet.'
        return self._stopped


class _Loop(NetBuilder):
    def __init__(self, iters=None, name=None):
        NetBuilder.__init__(self, name, _stop_blob_required=True)
        if iters is not None:
            self._inc = ops.Const(1)
            self._iter = ops.Const(0)
            self._num_iters = (
                iters if isinstance(iters, core.BlobReference)
                else ops.Const(iters))
        else:
            self._num_iters = None

    def iter(self):
        assert self._num_iters is not None, (
            'This loop does not have a number of iterations.')
        assert self._iter is not None, (
            'iter() must be called from inside the loop context')
        return self._iter

    def __enter__(self):
        builder = NetBuilder.__enter__(self)
        if self._num_iters is not None:
            ops.stop_if(ops.GE([self._iter, self._num_iters]))
        return builder

    def __exit__(self, type, *args):
        if type is None and self._num_iters is not None:
            self.current_net().Add([self._iter, self._inc], [self._iter])
        NetBuilder.__exit__(self, type, *args)


class _RunIf(_RunOnce):
    def __init__(self, cond_blob=None, name=None, _already_ran=None):
        _RunOnce.__init__(self, name)
        assert cond_blob or _already_ran
        self._is_else = cond_blob is None
        if _already_ran is None:
            self._else_blob = ops.Not(cond_blob)
            self._already_ran = ops.Const(False)
        else:
            self._already_ran = _already_ran
            self._else_blob = _already_ran if cond_blob is None else (
                ops.Or([_already_ran, ops.Not(cond_blob)]))

    def __enter__(self):
        r = _RunOnce.__enter__(self)
        ops.stop_if(self._else_blob)
        ops.Const(True, blob_out=self._already_ran)
        return r

    def Elif(self, cond, name=None):
        assert not self._is_else, 'Else not allowed for an Else.'
        return NetBuilder.current().add(_RunIf(
            cond, name=name or self.name, _already_ran=self._already_ran))

    def Else(self, name=None):
        assert not self._is_else, 'Elif not allowed for an Else.'
        return NetBuilder.current().add(
            _RunIf(name=name or self.name, _already_ran=self._already_ran))


class _RunIfNet(NetBuilder):
    """
    Generates a single net that uses If operator
    """
    def __init__(self, cond_blob, name=None):
        NetBuilder.__init__(self, name=name, _use_control_ops=True)
        assert cond_blob, 'Conditional blob is not specified for an If net'
        self._cond_blob = cond_blob
        self._then_net = None
        self._else_net = None

    def add(self, child):
        return NetBuilder.add(self, child)

    def __exit__(self, type, *args):
        if type is None:
            _then_nets = self._children
            self._reset_children()

            self._then_net = NetBuilder.merge_nets(
                _then_nets, self._lexical_scope)
            if not self._then_net:
                self._then_net = core.Net('empty_then_net')

            if_net = core.Net(self.name + '/if_net')
            add_if_op(if_net, self._cond_blob, self._lexical_scope,
                        self._then_net, self._else_net)

            self._current_net = if_net
            self._children = [if_net]
        NetBuilder.__exit__(self, type, *args)


class _RunElseNet(NetBuilder):
    """
    Else branch for _RunIfNet builder
    """
    def __init__(self, name=None):
        NetBuilder.__init__(self, name=name, _use_control_ops=True)
        parent = NetBuilder.current(required=False)
        assert parent and len(parent._children) > 0 and \
            isinstance(parent._children[-1], _RunIfNet), \
            'Invalid use of Else builder'
        self._if_builder = parent._children[-1]

    def __exit__(self, type, *args):
        if type is None:
            _else_nets = self._children
            self._reset_children()

            self._if_builder._else_net = NetBuilder.merge_nets(
                _else_nets, self._lexical_scope)
            if self._if_builder._else_net:
                if_else_net = core.Net(self.name + '/if_else_net')
                add_if_op(
                    if_else_net,
                    self._if_builder._cond_blob,
                    self._lexical_scope,
                    self._if_builder._then_net,
                    self._if_builder._else_net)
                self._if_builder._current_net = if_else_net
                self._if_builder._children = [if_else_net]
        NetBuilder.__exit__(self, type, *args)


class _RunWhileNet(NetBuilder):
    """
    Generates a single net that uses While operator
    """
    def __init__(self, name=None):
        NetBuilder.__init__(self, name=name, _use_control_ops=True)
        self._cond_builder = None

    def __exit__(self, type, *args):
        if type is None:
            assert self._cond_builder, \
                'Condition builder must be specified in While op'

            _cond_blob = self._cond_builder._cond_blob
            _cond_net = self._cond_builder._cond_net

            loop_body = self._children
            self._reset_children()
            loop_body_net = NetBuilder.merge_nets(
                loop_body, self._lexical_scope)
            if not loop_body_net:
                loop_body_net = core.Net('empty_loop_body_net')

            while_net = core.Net(self.name + '/while_net')
            add_while_op(while_net, _cond_blob, self._lexical_scope,
                            loop_body_net, _cond_net)

            self._current_net = while_net
            self._children = [while_net]
        NetBuilder.__exit__(self, type, *args)


class _RunWhileCondition(NetBuilder):
    """
    Computes loop's condition, used in the context of WhileNet.
    Last operator must have a single scalar boolean output that will be used
    as a condition value, no other blobs created in the condition net are
    visible outside of it
    """
    def __init__(self, name=None):
        NetBuilder.__init__(self, name=name, _use_control_ops=True)
        parent = NetBuilder.current(required=False)
        assert parent and isinstance(parent, _RunWhileNet), \
            'Invalid use of loop condition builder'
        assert not parent._cond_builder, \
            'Multiple loop condition builders specified'
        assert len(parent._children) == 0, \
            'Condition definition must be specified before the loop\'s body'
        parent._cond_builder = self
        self._cond_blob = None
        self._cond_net = None

    def __exit__(self, type, *args):
        if type is None:
            condition_body = self._children
            self._reset_children()
            self._cond_net = NetBuilder.merge_nets(
                condition_body, self._lexical_scope)
            assert self._cond_net, 'Invalid loop condition specified'
            assert len(self._cond_net.Proto().op) > 0, 'Invalid condition net'
            last_op = self._cond_net.Proto().op[-1]
            assert len(last_op.output) == 1, 'Invalid condition net'
            self._cond_blob = core.BlobReference(name=last_op.output[0], net=None)

            self._current_net = self._cond_net
            self._children = [self._cond_net]
        NetBuilder.__exit__(self, type, *args)
