"""
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.Vacuum()
matSubstrate_color = (0.55, 0.55, 0.55)
matSubstrate = ba.RefractiveMaterial("Substrate", matSubstrate_color, 3.2e-6, 3.2e-8)
matParticle_color = (0.86, 0.24, 0.18)
matParticle = ba.RefractiveMaterial("Ag", matParticle_color, 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.
    """
    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.suspend2D(ba.Dilute2D(0.001, particle))
    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.Ellipsoid(7., 8., 9.))
        self.runPlainFF(ba.HorizontalCylinder(5., 19.), 5e-12)
        self.runPlainFF(ba.HorizontalCylinder(5., 19., 1., 1.), 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.SphericalSegment(7., 9., 1.))
        self.runPlainFF(ba.SpheroidalSegment(7., 9., .9, 1.))
        self.runPlainFF(ba.EllipsoidalSegment(5., 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()
