"""
fft
===
Autogenerated DPF operator classes.
"""
from warnings import warn
from ansys.dpf.core.dpf_operator import Operator
from ansys.dpf.core.inputs import Input, _Inputs
from ansys.dpf.core.outputs import Output, _Outputs
from ansys.dpf.core.operators.specification import PinSpecification, Specification


class fft(Operator):
    """Computes the Fast Fourier Transform of given field or fields container
    that are assumed equally spaced and resampled to have 2^n values
    (use prepare_sampling_fft and time_freq_interpolation operators
    for that).

    Parameters
    ----------
    field : Field or FieldsContainer
        Field (real to complex fft is performed). or
        fields container with fields of the
        same dimension. if complex label is
        present, complex to complex fft
        performed. if time label is present,
        fft performed on each field.
    in_time_tfs : TimeFreqSupport, optional
        Specify input time freq support if the field
        or fields container don't have it.
    out_freq_tfs : TimeFreqSupport, optional
        Specify output time freq support, otherwise
        calculated from input
        timefreqsupport.
    scale_forward_transform : float, optional
        Scale for forward transform, default is 1.0.
    inplace : bool, optional
        True if inplace, default is false.
    calc_conjugated_coef : bool, optional
        True to trigger calculation of conjugated
        coefficient (real to complex fft
        only).


    Examples
    --------
    >>> from ansys.dpf import core as dpf

    >>> # Instantiate operator
    >>> op = dpf.operators.mapping.fft()

    >>> # Make input connections
    >>> my_field = dpf.Field()
    >>> op.inputs.field.connect(my_field)
    >>> my_in_time_tfs = dpf.TimeFreqSupport()
    >>> op.inputs.in_time_tfs.connect(my_in_time_tfs)
    >>> my_out_freq_tfs = dpf.TimeFreqSupport()
    >>> op.inputs.out_freq_tfs.connect(my_out_freq_tfs)
    >>> my_scale_forward_transform = float()
    >>> op.inputs.scale_forward_transform.connect(my_scale_forward_transform)
    >>> my_inplace = bool()
    >>> op.inputs.inplace.connect(my_inplace)
    >>> my_calc_conjugated_coef = bool()
    >>> op.inputs.calc_conjugated_coef.connect(my_calc_conjugated_coef)

    >>> # Instantiate operator and connect inputs in one line
    >>> op = dpf.operators.mapping.fft(
    ...     field=my_field,
    ...     in_time_tfs=my_in_time_tfs,
    ...     out_freq_tfs=my_out_freq_tfs,
    ...     scale_forward_transform=my_scale_forward_transform,
    ...     inplace=my_inplace,
    ...     calc_conjugated_coef=my_calc_conjugated_coef,
    ... )

    >>> # Get output data
    >>> result_fields_container = op.outputs.fields_container()
    """

    def __init__(
        self,
        field=None,
        in_time_tfs=None,
        out_freq_tfs=None,
        scale_forward_transform=None,
        inplace=None,
        calc_conjugated_coef=None,
        config=None,
        server=None,
    ):
        super().__init__(name="fft", config=config, server=server)
        self._inputs = InputsFft(self)
        self._outputs = OutputsFft(self)
        if field is not None:
            self.inputs.field.connect(field)
        if in_time_tfs is not None:
            self.inputs.in_time_tfs.connect(in_time_tfs)
        if out_freq_tfs is not None:
            self.inputs.out_freq_tfs.connect(out_freq_tfs)
        if scale_forward_transform is not None:
            self.inputs.scale_forward_transform.connect(scale_forward_transform)
        if inplace is not None:
            self.inputs.inplace.connect(inplace)
        if calc_conjugated_coef is not None:
            self.inputs.calc_conjugated_coef.connect(calc_conjugated_coef)

    @staticmethod
    def _spec():
        description = """Computes the Fast Fourier Transform of given field or fields container
            that are assumed equally spaced and resampled to have 2^n
            values (use prepare_sampling_fft and
            time_freq_interpolation operators for that)."""
        spec = Specification(
            description=description,
            map_input_pin_spec={
                0: PinSpecification(
                    name="field",
                    type_names=["field", "fields_container"],
                    optional=False,
                    document="""Field (real to complex fft is performed). or
        fields container with fields of the
        same dimension. if complex label is
        present, complex to complex fft
        performed. if time label is present,
        fft performed on each field.""",
                ),
                1: PinSpecification(
                    name="in_time_tfs",
                    type_names=["time_freq_support"],
                    optional=True,
                    document="""Specify input time freq support if the field
        or fields container don't have it.""",
                ),
                2: PinSpecification(
                    name="out_freq_tfs",
                    type_names=["time_freq_support"],
                    optional=True,
                    document="""Specify output time freq support, otherwise
        calculated from input
        timefreqsupport.""",
                ),
                3: PinSpecification(
                    name="scale_forward_transform",
                    type_names=["double"],
                    optional=True,
                    document="""Scale for forward transform, default is 1.0.""",
                ),
                4: PinSpecification(
                    name="inplace",
                    type_names=["bool"],
                    optional=True,
                    document="""True if inplace, default is false.""",
                ),
                5: PinSpecification(
                    name="calc_conjugated_coef",
                    type_names=["bool"],
                    optional=True,
                    document="""True to trigger calculation of conjugated
        coefficient (real to complex fft
        only).""",
                ),
            },
            map_output_pin_spec={
                0: PinSpecification(
                    name="fields_container",
                    type_names=["fields_container"],
                    optional=False,
                    document="""""",
                ),
            },
        )
        return spec

    @staticmethod
    def default_config(server=None):
        """Returns the default config of the operator.

        This config can then be changed to the user needs and be used to
        instantiate the operator. The Configuration allows to customize
        how the operation will be processed by the operator.

        Parameters
        ----------
        server : server.DPFServer, optional
            Server with channel connected to the remote or local instance. When
            ``None``, attempts to use the global server.
        """
        return Operator.default_config(name="fft", server=server)

    @property
    def inputs(self):
        """Enables to connect inputs to the operator

        Returns
        --------
        inputs : InputsFft
        """
        return super().inputs

    @property
    def outputs(self):
        """Enables to get outputs of the operator by evaluating it

        Returns
        --------
        outputs : OutputsFft
        """
        return super().outputs


class InputsFft(_Inputs):
    """Intermediate class used to connect user inputs to
    fft operator.

    Examples
    --------
    >>> from ansys.dpf import core as dpf
    >>> op = dpf.operators.mapping.fft()
    >>> my_field = dpf.Field()
    >>> op.inputs.field.connect(my_field)
    >>> my_in_time_tfs = dpf.TimeFreqSupport()
    >>> op.inputs.in_time_tfs.connect(my_in_time_tfs)
    >>> my_out_freq_tfs = dpf.TimeFreqSupport()
    >>> op.inputs.out_freq_tfs.connect(my_out_freq_tfs)
    >>> my_scale_forward_transform = float()
    >>> op.inputs.scale_forward_transform.connect(my_scale_forward_transform)
    >>> my_inplace = bool()
    >>> op.inputs.inplace.connect(my_inplace)
    >>> my_calc_conjugated_coef = bool()
    >>> op.inputs.calc_conjugated_coef.connect(my_calc_conjugated_coef)
    """

    def __init__(self, op: Operator):
        super().__init__(fft._spec().inputs, op)
        self._field = Input(fft._spec().input_pin(0), 0, op, -1)
        self._inputs.append(self._field)
        self._in_time_tfs = Input(fft._spec().input_pin(1), 1, op, -1)
        self._inputs.append(self._in_time_tfs)
        self._out_freq_tfs = Input(fft._spec().input_pin(2), 2, op, -1)
        self._inputs.append(self._out_freq_tfs)
        self._scale_forward_transform = Input(fft._spec().input_pin(3), 3, op, -1)
        self._inputs.append(self._scale_forward_transform)
        self._inplace = Input(fft._spec().input_pin(4), 4, op, -1)
        self._inputs.append(self._inplace)
        self._calc_conjugated_coef = Input(fft._spec().input_pin(5), 5, op, -1)
        self._inputs.append(self._calc_conjugated_coef)

    @property
    def field(self):
        """Allows to connect field input to the operator.

        Field (real to complex fft is performed). or
        fields container with fields of the
        same dimension. if complex label is
        present, complex to complex fft
        performed. if time label is present,
        fft performed on each field.

        Parameters
        ----------
        my_field : Field or FieldsContainer

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.field.connect(my_field)
        >>> # or
        >>> op.inputs.field(my_field)
        """
        return self._field

    @property
    def in_time_tfs(self):
        """Allows to connect in_time_tfs input to the operator.

        Specify input time freq support if the field
        or fields container don't have it.

        Parameters
        ----------
        my_in_time_tfs : TimeFreqSupport

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.in_time_tfs.connect(my_in_time_tfs)
        >>> # or
        >>> op.inputs.in_time_tfs(my_in_time_tfs)
        """
        return self._in_time_tfs

    @property
    def out_freq_tfs(self):
        """Allows to connect out_freq_tfs input to the operator.

        Specify output time freq support, otherwise
        calculated from input
        timefreqsupport.

        Parameters
        ----------
        my_out_freq_tfs : TimeFreqSupport

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.out_freq_tfs.connect(my_out_freq_tfs)
        >>> # or
        >>> op.inputs.out_freq_tfs(my_out_freq_tfs)
        """
        return self._out_freq_tfs

    @property
    def scale_forward_transform(self):
        """Allows to connect scale_forward_transform input to the operator.

        Scale for forward transform, default is 1.0.

        Parameters
        ----------
        my_scale_forward_transform : float

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.scale_forward_transform.connect(my_scale_forward_transform)
        >>> # or
        >>> op.inputs.scale_forward_transform(my_scale_forward_transform)
        """
        return self._scale_forward_transform

    @property
    def inplace(self):
        """Allows to connect inplace input to the operator.

        True if inplace, default is false.

        Parameters
        ----------
        my_inplace : bool

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.inplace.connect(my_inplace)
        >>> # or
        >>> op.inputs.inplace(my_inplace)
        """
        return self._inplace

    @property
    def calc_conjugated_coef(self):
        """Allows to connect calc_conjugated_coef input to the operator.

        True to trigger calculation of conjugated
        coefficient (real to complex fft
        only).

        Parameters
        ----------
        my_calc_conjugated_coef : bool

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> op.inputs.calc_conjugated_coef.connect(my_calc_conjugated_coef)
        >>> # or
        >>> op.inputs.calc_conjugated_coef(my_calc_conjugated_coef)
        """
        return self._calc_conjugated_coef


class OutputsFft(_Outputs):
    """Intermediate class used to get outputs from
    fft operator.

    Examples
    --------
    >>> from ansys.dpf import core as dpf
    >>> op = dpf.operators.mapping.fft()
    >>> # Connect inputs : op.inputs. ...
    >>> result_fields_container = op.outputs.fields_container()
    """

    def __init__(self, op: Operator):
        super().__init__(fft._spec().outputs, op)
        self._fields_container = Output(fft._spec().output_pin(0), 0, op)
        self._outputs.append(self._fields_container)

    @property
    def fields_container(self):
        """Allows to get fields_container output of the operator

        Returns
        ----------
        my_fields_container : FieldsContainer

        Examples
        --------
        >>> from ansys.dpf import core as dpf
        >>> op = dpf.operators.mapping.fft()
        >>> # Connect inputs : op.inputs. ...
        >>> result_fields_container = op.outputs.fields_container()
        """  # noqa: E501
        return self._fields_container
