from typing import Dict
from typing import Any


def _get_batchmm_opts(a_shape, a_strides, b_shape, b_strides, c_shape,
                      c_strides) -> Dict[str, Any]:
    """
    Detects whether a matrix multiplication is a batched matrix multiplication
    and returns its parameters (strides, batch size), or an empty dictionary if
    batched multiplication is not detected.
    :param a: Data descriptor for the first tensor.
    :param b: Data descriptor for the second tensor.
    :param c: Data descriptor for the output tensor (optional).
    :return: A dictionary with the following keys: sa,sb,sc (strides for a, b,
             and c); and b (batch size).
    """
    if len(a_shape) > 3 or len(b_shape) > 3 or (c_shape and len(c_shape) > 3):
        raise ValueError('Tensor dimensions too large for (batched) matrix '
                         'multiplication')
    if len(a_shape) <= 2 and len(b_shape) <= 2:
        return {}

    batch = None
    stride_a, stride_b, stride_c = 0, 0, 0
    if len(a_shape) == 3:
        batch = a_shape[0]
        stride_a = a_strides[0]
    if len(b_shape) == 3:
        if batch and batch != b_shape[0]:
            raise ValueError('Batch size mismatch for matrix multiplication')
        batch = b_shape[0]
        stride_b = b_strides[0]
    if c_shape and len(c_shape) == 3:
        if batch and batch != c_shape[0]:
            raise ValueError('Batch size mismatch for matrix multiplication')
        batch = c_shape[0]
        stride_c = c_strides[0]

    if batch is None:
        return {}

    return {'sa': stride_a, 'sb': stride_b, 'sc': stride_c, 'b': batch}