"""
Check automatic slicing by comparing scattering from particle in decorated_layer
- (A) without slicing
- (B) with slicing provoked by dividing decorated_layer into sublayers
"""

import unittest
import PyFuTestInfrastructure as infrastruct
import bornagain as ba

matVacuum = ba.RefractiveMaterial("Vacuum", 0, 0)
matSubstrate = ba.RefractiveMaterial("Substrate", 3.2e-6, 3.2e-8)
matParticle = ba.RefractiveMaterial("Ag", 1.2e-5, 5.4e-7)

R = 10.0
dz = 4.0  # shift beneath interface


def get_sample(particle, sliced):
    """
    Returns a sample, with given particles attached to substrate or vacuum layer.
    """

    layout = ba.ParticleLayout()
    layout.addParticle(particle)

    sample = ba.Sample()
    sample.addLayer(ba.Layer(matVacuum))
    if sliced:
        sample.addLayer(ba.Layer(matSubstrate, 5))
        sample.addLayer(ba.Layer(matSubstrate, 3))
        sample.addLayer(ba.Layer(matSubstrate, 2))
    else:
        sample.addLayer(ba.Layer(matSubstrate, 10))
    substrate = ba.Layer(matSubstrate)
    substrate.addLayout(layout)
    sample.addLayer(substrate)

    return sample


class SlicedSpheresTest(unittest.TestCase):

    def runPlainFF(self, ff, eps = 1e-14):
        particle = ba.Particle(matParticle, ff)
        d1 = infrastruct.run_simulation_MiniGISAS(get_sample(particle, False))
        d2 = infrastruct.run_simulation_MiniGISAS(get_sample(particle, False))
        self.assertTrue(ba.checkRelativeDifference(d1, d2, eps))

    def testSlicingPlainFF(self):
        self.runPlainFF(ba.Cone(8., 9., 80*ba.deg))
        self.runPlainFF(ba.Cylinder(3., 9.))
        self.runPlainFF(ba.EllipsoidalCylinder(3., 4., 9.))
        # self.runPlainFF(ba.HemiEllipsoid(7., 8., 9.)) # yet unsupported
        self.runPlainFF(ba.HorizontalCylinder(5., 19.), 5e-12)
        self.runPlainFF(ba.HorizontalCylinder(5., 19., -4., 4.), 5e-12)
        self.runPlainFF(ba.HorizontalCylinder(6., 19., -3., 3.), 5e-12)
        self.runPlainFF(ba.Sphere(5.))
        self.runPlainFF(ba.Spheroid(4., 4.))
        self.runPlainFF(ba.TruncatedSphere(7., 9., 1.))
        self.runPlainFF(ba.TruncatedSpheroid(7., 9., .9, 1.))

        # self.runPlainFF(ba.PlatonicTetrahedron(12.)) # yet unsupported
        self.runPlainFF(ba.Prism3(8., 10.))
        self.runPlainFF(ba.Prism6(4., 9.))
        self.runPlainFF(ba.Pyramid3(8., 10., 80*ba.deg))
        self.runPlainFF(ba.Pyramid4(8., 9., 80*ba.deg))
        self.runPlainFF(ba.Pyramid6(18., 8., 40*ba.deg))


if __name__ == '__main__':
    unittest.main()
