from __future__ import absolute_import
import numpy as nm

from sfepy.base.base import load_classes, Struct
from sfepy import get_paths

def transform_basis(transform, bf):
    """
    Transform a basis `bf` using `transform` array of matrices.
    """
    if bf.ndim == 3:
        nbf = nm.einsum('cij,qdj->cqdi', transform, bf, order='C')

    elif bf.ndim == 4:
        if bf.shape[0] == 1:
            nbf = nm.einsum('cij,qdj->cqdi', transform, bf[0], order='C')

        else:
            nbf = nm.einsum('cij,cqdj->cqdi', transform, bf, order='C')

    # Note: the 2nd derivatives are not supported here.
    # Workaround for NumPy 1.14.0 - order is ignored(?)
    nbf = nm.ascontiguousarray(nbf)

    return nbf

class PolySpace(Struct):
    """Abstract polynomial space class."""
    _all = None

    keys = {
        (0, 1) : 'simplex',
        (1, 2) : 'simplex',
        (2, 3) : 'simplex',
        (3, 4) : 'simplex',
        (2, 4) : 'tensor_product',
        (3, 8) : 'tensor_product',
    }

    @staticmethod
    def any_from_args(name, geometry, order, base='lagrange',
                      force_bubble=False):
        """
        Construct a particular polynomial space classes according to the
        arguments passed in.
        """
        if name is None:
            name = PolySpace.suggest_name(geometry, order, base, force_bubble)

        if PolySpace._all is None:
            ps_files = get_paths('sfepy/discrete/fem/poly_spaces.py')
            ps_files += 
get_paths('sfepy/discrete/dg/poly_spaces.py')