import json
import numpy as np
from material.orthotropic import Orthotropic
from ply.ply import Ply
from laminate.laminate import Laminate

materialFile = "material.json"
plyFile = "ply.json"
laminateFile = "laminate.json"
A = np.array([[113.2, 84.6, 0.], [84.6, 113.0, 0], [0., 0., 93.2]])
B = np.array([[0., 0., 21.4], [0., 0., 21.4], [21.4, 21.4, 0.]])
D = np.array([[37.8, 28.2, 0.], [28.2, 37.8, 0.], [0., 0., 31.1]])

class TestLaminateClass():
    """Unittest for Laminate."""

    materials = {}
    plies = {}
    laminates = {}

    def setup_class(cls):
        """Setup class from material, ply, and laminate file."""

        with open(materialFile, 'r') as fh:
            jsonData = json.load(fh)
        for materialDict in jsonData["materials"]:
            matID = materialDict["matID"]
            E1 = materialDict["E1"]
            E2 = materialDict["E2"]
            G12 = materialDict["G12"]
            G13 = materialDict["G13"]
            G23 = materialDict["G23"]
            v12 = materialDict["v12"]
            cls.materials[matID] = Orthotropic(matID=matID, E1=E1, E2=E2, G12=G12, 
            G13=G13, G23=G23, v12=v12)

        with open(plyFile, 'r') as fh:
            jsonData = json.load(fh)
        for plyDict in jsonData["plies"]:
            plyID = plyDict["plyID"]
            angle = plyDict["angle"]
            material = cls.materials[plyDict["material"]]
            thickness = plyDict["thickness"]
            cls.plies[plyID] = Ply(plyID=plyID, angle=angle, material=material, 
            thickness=thickness)

        with open(laminateFile, 'r') as fh:
            jsonData = json.load(fh)
        for laminateDict in jsonData["laminates"]:
            lamID = laminateDict["lamID"]
            stacking_sequence = [cls.plies[str(plyID)] for plyID in laminateDict["stacking_sequence"]]
            offset = laminateDict["offset"]
            cls.laminates[lamID] = Laminate(lamID=lamID, 
            stacking_sequence=stacking_sequence,
            offset=offset)
            if "A" in laminateDict:
                A11, A12, A16, A22, A26, A66, A44, A45, A55 = laminateDict["A"]
                cls.laminates[lamID]._A = np.array([[A11, A12, A16], [A12, A22, A26], [A16, A26, A66]])
                cls.laminates[lamID]._A44 = A44
                cls.laminates[lamID]._A45 = A45
                cls.laminates[lamID]._A55 = A55
            if "B" in laminateDict:
                B11, B12, B16, B22, B26, B66 = laminateDict["B"]
                cls.laminates[lamID]._B = np.array([[B11, B12, B16], [B12, B22, B26], [B16, B26, B66]])
            if "D" in laminateDict:
                D11, D12, D16, D22, D26, D66 = laminateDict["D"]
                cls.laminates[lamID]._D = np.array([[D11, D12, D16], [D12, D22, D26], [D16, D26, D66]])

    def test_can_read_laminate(self):
        """Unittest to check if properly initialized."""

        assert "1" in self.laminates

    def test_laminate_A1(self):
        """Unittest laminate A (calculated) matrix."""

        print("\n", self.laminates["1"].A)
        np.testing.assert_array_almost_equal(self.laminates["1"].A, A, decimal=0)

    def test_laminate_A2(self):
        """Unittest laminate A (input) matrix."""

        np.testing.assert_array_almost_equal(self.laminates["2"].A, A, decimal=0)

    def test_laminate_B1(self):
        """Unittest laminate B (calculated) matrix."""

        print("\n", self.laminates["1"].B)
        np.testing.assert_array_almost_equal(self.laminates["1"].B, B, decimal=0)

    def test_laminate_B2(self):
        """Unittest laminate B (input) matrix."""

        np.testing.assert_array_almost_equal(self.laminates["2"].B, B, decimal=0)

    def test_laminate_D1(self):
        """Unittest laminate D (calculated) matrix."""

        print("\n", self.laminates["1"].D)
        np.testing.assert_array_almost_equal(self.laminates["1"].D, D, decimal=0)

    def test_laminate_D2(self):
        """Unittest laminate D (input) matrix."""

        np.testing.assert_array_almost_equal(self.laminates["2"].D, D, decimal=0)

    def test_laminate_ABD(self):
        """Unittest laminate ABD matrix."""

        print("\n", self.laminates["1"].ABD)