"""
Classes holding information on global DOFs and mapping of all DOFs -
equations (active DOFs).

Helper functions for the equation mapping.
"""
import numpy as nm
import scipy.sparse as sp

from sfepy.base.base import assert_, Struct, basestr
from sfepy.discrete.functions import Function
from sfepy.discrete.conditions import get_condition_value, EssentialBC, \
    PeriodicBC, DGPeriodicBC, DGEssentialBC


def expand_nodes_to_dofs(nods, n_dof_per_node):
    """
    Expand DOF node indices into DOFs given a constant number of DOFs
    per node.
    """
    dofs = nm.repeat(nods, n_dof_per_node)
    dofs.shape = (nods.shape[0], n_dof_per_node)

    idof = nm.arange(n_dof_per_node, dtype=nm.int32)

    dofs = n_dof_per_node * dofs + idof

    return dofs

def expand_nodes_to_equations(nods, dof_names, all_dof_names):
    """
    Expand vector of node indices to equations (DOF indices) based on
    the DOF-per-node count.

    DOF names must be already canonized.

    Returns
    -------
    eq : array
        The equations/DOF indices in the node-by-node order.
    """
    dpn = len(all_dof_names)
    nc = len(dof_names)

    eq = nm.empty(len(nods) * nc, dtype=nm.int32)
    for ii, dof in enumerate(dof_names):
        idof = all_dof_names.index(dof)
        eq[ii::nc] = dpn * nods + idof
    return eq

def resolve_chains(master_slave, chains):
    """
    Resolve EPBC chains - e.g. in corner nodes.
    """
    for chain in chains:
        slave = chain[-1]
        master_slave[chain[:-1]] = slave + 1
        master_slave[slave] = - chain[0] - 1 # Any of masters...

def group_chains(chain_list):
    """
    Group EPBC chains.
    """
    chains = []
    while len(chain_list):
        chain = set(chain_list.pop(0))
        ## print ':', chain
        ii = 0
        while ii < len(chain_list):
            c1 = sorted(chain_list[ii])
            ## print '--', ii, c1, chain
            is0 = c1[0] in chain
            is1 = c1[1] in chain

            if is0 and is1:
                chain_list.pop(ii)
            elif is0 or is1:
                chain.update(c1)
                chain_list.pop(ii)
                ii = 0
            else:
                ii += 1
            ## print ii, chain, chain_list
        ## print '->', chain
        ## print chain_list

        chains.append(list(chain))

    ## print 'EPBC chain groups:', chains
    aux = {}
    for chain in chains:
        aux.setdefault(len(chain), [0])[0] += 1
    ## print 'EPBC chain counts:', aux

    return chains

class DofInfo(Struct):
    """
    Global DOF information, i.e. ordering of DOFs of the state (unknown)
    variables in the global state vector.
    """

    def __init__(self, name):
        
Struct.__init__(self, name=name)