package Sidef::Types::Number::Complex;

# No reference is blessed in this class.

use utf8;
use 5.016;

use parent qw(
  Sidef::Types::Number::Number
);

our ($PREC, $ROUND);

BEGIN {
    *PREC  = \$Sidef::Types::Number::Number::PREC;
    *ROUND = \$Sidef::Types::Number::Number::ROUND;
}

sub new {
    my (undef, $real, $imag) = @_;

    $real //= Sidef::Types::Number::Number::ZERO;
    $imag //= Sidef::Types::Number::Number::ZERO;

    Sidef::Types::Number::Number::_valid(\$real) if ref($real);
    Sidef::Types::Number::Number::_valid(\$imag) if ref($imag);

    if (ref($real) eq 'Sidef::Types::Number::Number') {
        $real = $$real;
    }
    else {
        $real =
          defined($real)
          ? Sidef::Types::Number::Number::_str2obj("$real")
          : ${(Sidef::Types::Number::Number::ZERO)};

        $real = Sidef::Types::Number::Number::_any2mpz($real) if !ref($real);
    }

    if (defined($imag)) {

        if (ref($imag) eq 'Sidef::Types::Number::Number') {
            $imag = $$imag;
        }
        else {
            $imag = Sidef::Types::Number::Number::_str2obj("$imag");
        }

        $imag = Sidef::Types::Number::Number::_any2mpz($imag) if !ref($imag);

        my $c   = Math::MPC::Rmpc_init2($PREC);
        my $sig = join(' ', ref($real), ref($imag));

        # GMPz
        if ($sig eq q(Math::GMPz Math::GMPz)) {
            Math::MPC::Rmpc_set_z_z($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::GMPz Math::GMPq)) {
            Math::MPC::Rmpc_set_z_q($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::GMPz Math::MPFR)) {
            Math::MPC::Rmpc_set_z_fr($c, $real, $imag, $ROUND);
        }

        # GMPq
        elsif ($sig eq q(Math::GMPq Math::GMPq)) {
            Math::MPC::Rmpc_set_q_q($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::GMPq Math::GMPz)) {
            Math::MPC::Rmpc_set_q_z($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::GMPq Math::MPFR)) {
            Math::MPC::Rmpc_set_q_fr($c, $real, $imag, $ROUND);
        }

        # MPFR
        elsif ($sig eq q(Math::MPFR Math::MPFR)) {
            Math::MPC::Rmpc_set_fr_fr($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::MPFR Math::GMPz)) {
            Math::MPC::Rmpc_set_fr_z($c, $real, $imag, $ROUND);
        }
        elsif ($sig eq q(Math::MPFR Math::GMPq)) {
            Math::MPC::Rmpc_set_fr_q($c, $real, $imag, $ROUND);
        }

        # Anything else
        else {
            $real = Sidef::Types::Number::Number::_any2mpc($real);
            $imag = Sidef::Types::Number::Number::_any2mpc($imag);
            Math::MPC::Rmpc_set($c, $imag, $ROUND);
            Math::MPC::Rmpc_mul_i($c, $c, 1, $ROUND);
            Math::MPC::Rmpc_add($c, $c, $real, $ROUND);
        }

        bless \$c, 'Sidef::Types::Number::Number';
    }
    else {
        my $c = Sidef::Types::Number::Number::_any2mpc($real);
        bless \$c, 'Sidef::Types::Number::Number';
    }
}

*call = \&new;

1
