# Copyright (C) 2021 Arm Limited or its affiliates. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
# Licensed 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
#
# 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.
# Description:
# The TosaSupportedOperators class which is a collection of all supported operators and parameter checks.
from collections import defaultdict

from .data_type import DataType
from .operation import Op
from .supported_operators_util import docstring_format_args
from .supported_operators_util import list_formatter
from .tosa_mapping import optype_to_tosa_op_type


class TosaSupportedOperators:
    # TODO currently sparsely populated
    # Categorised lists of supported operators
    convolution_ops = set((Op.Conv2DBias,))
    depthwise_convolution_ops = set((Op.DepthwiseConv2DBias,))
    convolution_like_ops = convolution_ops | depthwise_convolution_ops

    # TODO depending on what will be committed
    max_pooling_ops = Op.op_set(Op.is_maxpool_op)
    avg_pooling_ops = Op.op_set(Op.is_avgpool_op)
    pooling_ops = max_pooling_ops | avg_pooling_ops
    fc_vector_products = set((Op.FullyConnected,))

    mac_main_ops = convolution_like_ops | pooling_ops | fc_vector_products
    memory_only_ops = set((Op.Reshape, Op.Transpose, Op.Concat, Op.SplitSliceRead,))
    binary_elem_wise_add_mul_sub = set((Op.Add, Op.Mul, Op.RescaleMul, Op.Sub,))
    elem_wise_ops = binary_elem_wise_add_mul_sub
    type_conversion_ops = set((Op.Rescale,))
    relu_ops = set((Op.Clamp, Op.ReluN,))
    activation_ops = relu_ops | set((Op.Table,))
    pad_ops = set((Op.Pad,))

    rank_unlimited_ops = set((Op.Concat, Op.Reshape))
    rank6_limited_ops = elem_wise_ops
    batch_enabled_ops = rank6_limited_ops | rank_unlimited_ops
    large_tens_dims_enabled_ops = batch_enabled_ops | set((Op.SplitSliceRead,))
    npu_post_ops = activation_ops

    supported_operators = mac_main_ops | type_conversion_ops | npu_post_ops | memory_only_ops | elem_wise_ops | pad_ops

    # Supported data types
    # TODO will differ compared to TensorFlow Lite, currently set to the same
    supported_op_dtypes = set((DataType.uint8, DataType.int8, DataType.int16, DataType.int32))  # TODO add bool
    tens_dim_range = (1, 65535)  # TODO HW limitation, that is to be resolved in SW

    def __init__(self):
        # Setup the generic constraints. Note: the order matters
        self.generic_constraints = []
        self.generic_constraints.append(TosaSupportedOperators.constraint_tens_dtype)
        self.generic_constraints.append(TosaSupportedOperators.constraint_tens_dimension)  # TODO not supported yet
        self.generic_constraints.append(TosaSupportedOperators.constraint_rank)  # TODO not supported for all ops yet
        self.generic_constraints.append(TosaSupportedOperators.constraint_batch)  # TODO not supported for all ops yet

        # Setup specific constraints. Note: the order matters
        self.specific_constraints = defaultdict(list)

        self.specific_constraints[Op.Transpose].append(TosaSupportedOperators.constraint_ifm_producer)
        self.specific_constraints[Op.Pad].append(TosaSupportedOperators.constraint_padding_producer)
        self.specific_constraints[Op.Table].append(TosaSupportedOperators.constraint_table_dtype)
        self.specific_constraints[Op.Table].append(TosaSupportedOperators.constraint_table_producer)

        # Depthwise Conv specific checks:
        for op_type in TosaSupportedOperators.depthwise_convolution_ops:
            self.specific_constraints[op_type].append(TosaSupportedOperators.constraint_depth_multiplier)

        # Avgpool specific checks
        for op_type in TosaSupportedOperators.avg_pooling_ops:
            self.specific_constraints[op_type].append(TosaSupportedOperators.constraint_padding)

    def is_operator_supported(self, op):
        ext_type = optype_to_tosa_op_type(op.type)
        if op.type not in TosaSupportedOperators.supported_operators:
            if op.type not in (Op.Placeholder, Op.SubgraphInput, Op.Const):
                print(f"Info: {ext_type} '{op.name}' is not a NPU op")
            return False

        for constraint in self.generic_constraints + self.specific_constraints[op.type]:
            valid, extra = constraint(op)
            if not valid:
                print(f"Warning: {ext_type} '{op.name}' is not supported on the NPU")
                print(f" - {constraint.__doc__}")
                if extra:
                    print(f"   {extra}")
                return False

        return True

    # TODO this function is the same for TensorFlow Lite, but input might differ
    @classmethod
    @docstring_format_args([list_formatter(supported_op_dtypes)])
    def constraint_tens_dtype(cls, op):
        "Tensors must be of type: {}"
        valid = True
        extra = []
        tensors = [tens for tens in op.get_ifm_ifm2_weights_ofm() if tens]
        if not tensors:
            tensors = [tens for tens in op.inputs if tens]
        for tens in tensors:
            if tens.dtype not in cls.supported_op_dtypes:
                valid = False
                extra.append(f"Tensor '{tens.name}' has data type: {tens.dtype}")
        return valid, ", ".join(extra)

    # TODO Duplicates check present for TFLite. But it is only temporarily added
    # This is for a HW limitation, that is to be resolved in SW later on
    @classmethod
    @docstring_format_args(tens_dim_range)
    def constraint_tens_dimension(self, op):
        "Tensor dimensions must be in the range [{}, {}]"
        tens_min, tens_max = self.tens_dim_range
        valid = True
        extra = []
        if op.type not in self.large_tens_dims_enabled_ops:
            tensors = [tens for tens in op.get_ifm_ifm2_weights_ofm() if tens]
            if not tensors:
                tensors = [tens for tens in op.inputs if tens]
            for tens in tensors:
                if not all(tens_min <= dim <= tens_max for dim in tens.shape):
                    valid = False
                    extra.append(f"Tensor '{tens.name}' has shape: {tens.shape}")
        return valid, ", ".join(extra)

    # TODO This is for a HW limitation, that is to be resolved in SW later on
    @classmethod
    def constraint_rank(self, op):
        "Tensor rank must be <= 6 or <= 4 depending on operator"
        valid = True
        extra = []
        if op.type not in self.rank_unlimited_ops:
            if op.type in self.rank6_limited_ops:
                rank_limit = 6
            else:
                rank_limit = 4
            tensors = [tens for tens in op.get_ifm_ifm2_weights_ofm() if tens]
            if not tensors:
                tensors = [tens for tens in op.inputs if tens]
            for tens in tensors:
                rank = len(tens.shape)
                if not rank <= rank_limit:
                    valid = False
                    extra.append(
                        f"Tensor '{tens.name}' has rank: {rank}, rank limit is currently {rank_limit}"
                        f" for op of type {op.type}"
                    )
        return valid, ", ".join(extra)

    # TODO This is for a HW limitation, that is to be resolved in SW later on
    @classmethod
    def constraint_batch(self, op):
        "If Tensor rank is 4 batch of ifms/ofm must be 1"
        valid = True
        extra = []
        if op.type not in self.batch_enabled_ops:
            tensors = [tens for tens in op.get_ifm_ifm2_ofm() if tens]
            if not tensors:
                tensors = [tens for tens in op.inputs if tens]
            for tens in tensors:
                rank = len(tens.shape)
                if rank == 4 and tens.shape[0] != 1:
                    valid = False
                    extra.append(f"Tensor '{tens.name}' has rank: 4 and N: {tens.shape[0]}")
        return valid, ", ".join(extra)

    @staticmethod
    def constraint_ifm_producer(cls, op):
        "Input must be constant data"
        valid = op.ifm.ops and op.ifm.ops[0].type == Op.Const
        return valid, "Op has ifm with non-constant data"

    @staticmethod
    def constraint_padding(op):
        # TODO Only support for when global scaling can be used.
        # That is when there is padding no padding
        "Avgpool only supported for no padding"
        top, left, _, _ = op.attrs["explicit_padding"]
        valid = top == 0 and left == 0

        return valid, "Avgpool with pad_top {top} and pad_left {left}"

    # TODO limit padding to be const data for now.
    # For TFLite it is assumed to be constant.
    @staticmethod
    def constraint_padding_producer(op):
        "Input must be constant data"
        valid = op.inputs[1].ops and op.inputs[1].ops[0].type == Op.Const
        return valid, "PAD Op with non-constant data padding"

    # TODO duplicates tflite_supported operators, but support for depth multiplier should be added at a later stage
    @staticmethod
    def constraint_depth_multiplier(op):
        "For depth multipliers > 1, IFM channels must be 1 and OFM channels must be equal to the depth multiplier"
        depth_multiplier = op.attrs.get("depth_multiplier", 1)
        if depth_multiplier > 1:
            ifm_channels = op.ifm.shape[3]
            ofm_channels = op.ofm.shape[3]
            valid = (ifm_channels == 1) and (ofm_channels == depth_multiplier)
            extra = (
                f"Op has ifm_channels={ifm_channels}, ofm_channels={ofm_channels}"
                f" and depth_multiplier={depth_multiplier}"
            )
            return valid, extra
        return True, "Op has depth_multiplier=1"

    # TODO Table operator support limited to int8 for now.
    # For TFLite it is assumed to be constant.
    @staticmethod
    def constraint_table_dtype(op):
        "Only supported is int8"
        valid = True
        tensors = [op.ifm, op.ofm, op.inputs[1]]
        for tens in tensors:
            if tens.dtype != DataType.int8:
                valid = False
        return valid, "Table operator with non int8 tensor"

    # TODO limit table to be constant data for now.
    # Can it be non-constant?
    @staticmethod
    def constraint_table_producer(op):
        "Input must be constant data"
        valid = op.inputs[1].ops and op.inputs[1].ops[0].type == Op.Const
        return valid, "Table Op with non-constant table input"
