# Source code for xga.sourcetools.deproj

#  This code is a part of X-ray: Generate and Analyse (XGA), a module designed for the XMM Cluster Survey (XCS).

from typing import Union

import numpy as np
from astropy.units import Quantity, UnitConversionError

-> Union[np.ndarray, Quantity]:
"""
This function calculates the volume intersection matrix of a set of circular annuli and a
set of spherical shells. It is assumed that the annuli and shells have the same x and y origin. The
intersection is derived using simple geometric considerations, have a look in the appendix of DOI 10.1086/300836.

:param ndarray/Quantity ann_radii: The radii of the circular annuli (DOES NOT need to be the same
:return: A 2D array containing the volumes of intersections between the circular annuli defined by
i_ann and o_ann, and the spherical shells defined by i_sph and o_sph. Annular radii are along the 'x' axis
and shell radii are along the 'y' axis.
:rtype: Union[np.ndarray, Quantity]
"""
raise UnitConversionError("If quantities are passed, they must be in the same units.")
pass
pass
else:
raise TypeError("shell_radii and ann_radii must either both be astropy quantities or numpy arrays, "
"you cannot mix the two")

# The main term which makes use of the radii of the shells and annuli.
# The use of clip enforces that none of the terms can be less than 0, as we don't care
#  about those intersections, you can't have a negative volume. The None passed to clip is just to tell it
#  that there is no upper limit that we wish to enforce.
main_term = np.power(np.clip((o_sph ** 2 - i_ann ** 2), 0, None), 3 / 2) - \
np.power(np.clip((o_sph ** 2 - o_ann ** 2), 0, None), 3 / 2) + \
np.power(np.clip((i_sph ** 2 - o_ann ** 2), 0, None), 3 / 2) - \
np.power(np.clip((i_sph ** 2 - i_ann ** 2), 0, None), 3 / 2)

# Multiply by the necessary constants and return.
return (4 / 3) * np.pi * main_term

"""
Silly little function that calculates the volume of a spherical shell with inner radius inn_radius and outer

:return: The volume of the specified shell
:rtype: Union[Quantity, np.ndarray]
"""
raise UnitConversionError("If quantities are passed, they must be in the same units.")
pass
pass
else:
raise TypeError("inn_radius and out_radius must either both be astropy quantities or numpy arrays, "
"you cannot mix the two")

outer_vol = (4/3) * np.pi * out_radius**3
inner_vol = (4/3) * np.pi * inn_radius**3

return outer_vol - inner_vol

# def temp_onion(proj_prof: ProjectedGasTemperature1D) -> GasTemperature3D:
#     """
#     This function will generate deprojected, three-dimensional, gas temperature profile from a projected profile using
#     the 'onion peeling' deprojection method. The function is an implementation of a fairly old technique, though it
#     has been used recently in https://doi.org/10.1051/0004-6361/201731748. For a more in depth discussion of this
#     technique and its uses I would currently recommend https://doi.org/10.1051/0004-6361:20020905.
#
#     :param ProjectedGasTemperature1D proj_prof: A projected cluster temperature profile, which the
#         user wants to use to infer the 3D temperature profile.
#     :return: The deprojected temperature profile.
#     :rtype: GasTemperature3D
#     """
#
#     pass