#!/usr/bin/env python3
# -*- encoding: utf-8 -*-

#  Licensed to the Apache Software Foundation (ASF) under one
#  or more contributor license agreements.  See the NOTICE file
#  distributed with this work for additional information
#  regarding copyright ownership.  The ASF licenses this file
#  to you under the Apache License, Version 2.0 (the
#  "License"); you may not use this file except in compliance
#  with the License.  You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing,
#  software distributed under the License is distributed on an
#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
#  specific language governing permissions and limitations
#  under the License.

'''task_hook.py: modules for supporting task hooks for topology'''
from collections import namedtuple
from abc import abstractmethod

class ITaskHook:
  """ITaskHook is an interface for defining task hooks for a topology"""

  @abstractmethod
  def prepare(self, conf, context):
    """Called after the spout/bolt's initialize() method is called

    :param conf: component-specific configuration passed to the topology
    :param context: topology context
    """

  @abstractmethod
  def clean_up(self):
    """Called just before the spout/bolt's cleanup method is called"""

  @abstractmethod
  def emit(self, emit_info):
    """Called every time a tuple is emitted in spout/bolt

    :param emit_info: EmitInfo object
    """

  @abstractmethod
  def spout_ack(self, spout_ack_info):
    """Called in spout every time a tuple gets acked

    :param spout_ack_info: SpoutAckInfo object
    """

  @abstractmethod
  def spout_fail(self, spout_fail_info):
    """Called in spout every time a tuple gets failed

    :param spout_fail_info: SpoutFailInfo object
    """

  @abstractmethod
  def bolt_execute(self, bolt_execute_info):
    """Called in bolt every time a tuple gets executed

    :param bolt_execute_info: BoltExecuteInfo object
    """

  @abstractmethod
  def bolt_ack(self, bolt_ack_info):
    """Called in bolt every time a tuple gets acked

    :param bolt_ack_info: BoltAckInfo object
    """

  @abstractmethod
  def bolt_fail(self, bolt_fail_info):
    """Called in bolt every time a tuple gets failed

    :param bolt_fail_info: BoltFailInfo object
    """


##################################################################################
## Below are named tuples for each information                                  ##
## Topology writers never need to create an instance of the following classes,  ##
## as they are automatically created by the Heron Instance                      ##
##################################################################################

EmitInfo = namedtuple('EmitInfo', 'values, stream_id, task_id, out_tasks')
"""Information about emit

:ivar values: (list) values emitted
:ivar stream_id: (str) stream id into which tuple is emitted
:ivar task_id: (int) task id on which emit() was called
:ivar out_tasks: (list) list of custom grouping target task id
"""

SpoutAckInfo = namedtuple('SpoutAckInfo', 'message_id, spout_task_id, complete_latency_ms')
"""Information about Spout's Acking of a tuple

:ivar message_id: message id to which an acked tuple was anchored
:ivar spout_task_id: (int) task id of spout
:ivar complete_latency_ms: (float) complete latency in ms
"""

SpoutFailInfo = namedtuple('SpoutFailInfo', 'message_id, spout_task_id, fail_latency_ms')
"""Information about Spout's Failing of a tuple

:ivar message_id: message id to which an acked tuple was anchored
:ivar spout_task_id: (int) task id of spout
:ivar fail_latency_ms: (float) fail latency in ms
"""

BoltExecuteInfo = \
  namedtuple('BoltExecuteInfo', 'heron_tuple, executing_task_id, execute_latency_ms')
"""Information about Bolt's executing of a tuple

:ivar heron_tuple: (HeronTuple) tuple that is executed
:ivar executing_task_id: (int) task id of bolt
:ivar execute_latency_ms: (float) execute latency in ms
"""

BoltAckInfo = namedtuple('BoltAckInfo', 'heron_tuple, acking_task_id, process_latency_ms')
"""Information about Bolt's acking of a tuple

:ivar heron_tuple: (HeronTuple) tuple that is acked
:ivar acking_task_id: (int) task id of bolt
:ivar process_latency_ms: (float) process latency in ms
  """

BoltFailInfo = namedtuple('BoltFailInfo', 'heron_tuple, failing_task_id, fail_latency_ms')
"""Information about Bolt's failing of a tuple

:ivar heron_tuple: (HeronTuple) tuple that is failed
:ivar failing_task_id: (int) task id of bolt
:ivar fail_latency_ms: (float) fail latency in ms
"""
