# -*- coding: utf-8 -*-
"""Module for quadrature.

@author: Laura C. Kühle

"""
from abc import ABC
from numpy import ndarray
import numpy.polynomial.legendre as leg


class Quadrature(ABC):
    """Abstract class for quadrature.

    A quadrature is used to determine the approximation of a definite integral
    of a function.

    Attributes
    ----------
    name : str
        String of class name.
    num_nodes : int
        Number of nodes (evaluation points) per cell used for approximation.
    nodes : ndarray
        Nodes (evaluation points) per cell used for approximation.
    weights : ndarray
        Weights used for approximation calculation.

    """

    def __init__(self, config: dict) -> None:
        """Initialize Quadrature.

        Parameters
        ----------
        config : dict
            Additional parameters for quadrature.

        """
        self._reset(config)

    def _reset(self, config: dict) -> None:
        """Reset instance variables.

        Parameters
        ----------
        config : dict
            Additional parameters for quadrature.

        """
        self._num_nodes = None
        self._nodes = None
        self._weights = None

    @property
    def name(self) -> str:
        """Return string of class name."""
        return self.__class__.__name__

    @property
    def num_nodes(self) -> str:
        """Return number of nodes."""
        return self._num_nodes

    @property
    def nodes(self) -> ndarray:
        """Return nodes."""
        return self._nodes

    @property
    def weights(self) -> ndarray:
        """Return evaluation weights."""
        return self._weights


class Gauss(Quadrature):
    """Class for Gaussian quadrature.

    Attributes
    ----------
    name : str
        String of class name.
    num_nodes : int
        Number of nodes (evaluation points) per cell used for approximation.
    nodes : ndarray
        Nodes (evaluation points) per cell used for approximation.
    weights : ndarray
        Weights used for approximation calculation.

    """

    def _reset(self, config: dict) -> None:
        """Reset instance variables.

        Parameters
        ----------
        config : dict
            Additional parameters for quadrature.

        """
        super()._reset(config)

        # Unpack necessary configurations
        self._num_nodes = config.pop('num_eval_points', 6)

        self._nodes, self._weights = leg.leggauss(self._num_nodes)

    @property
    def name(self) -> str:
        """Return string of class name."""
        return self.__class__.__name__ + str(self._num_nodes)