import numpy as np
import laminate as lam
import params as p
import computations as comp

def get_load(layup, L):
    h = lam.laminateThickness(layup)
    r_outer = p.R_inner + h
    I = np.pi * ((r_outer * 2) ** 4 - (p.R_inner * 2) ** 4) / 64

    q = (np.pi * p.R_inner ** 2 * p.rhow + np.pi * (r_outer ** 2 - p.R_inner ** 2) * p.m['rho']) * p.g
    M = q * L ** 2 / 8

    Nx = M * h * r_outer / I
    Ny = p.max_pres * r_outer

    N = np.array([Nx, Ny, 0])
    return N

def get_strains(layup, L):
    h = lam.laminateThickness(layup)
    r_outer = p.R_inner + h
    I = np.pi * ((r_outer * 2)**4 - (p.R_inner * 2)**4) / 64

    q = (np.pi * p.R_inner**2 * p.rhow + np.pi * (r_outer**2 - p.R_inner**2) * p.m['rho']) * p.g
    M = q * L**2 / 8

    Nx = M * h * r_outer / I
    Ny = p.max_pres * r_outer

    N = np.array([Nx, Ny, 0])
    A = lam.computeA(layup)
    strain = np.linalg.solve(A, N)
    return strain



def get_strains2(layup, L):
    h = lam.laminateThickness(layup)
    Ex, Ey = get_effective(layup)

    r_outer = p.R_inner + h
    I = np.pi * ((r_outer * 2) ** 4 - (p.R_inner * 2) ** 4) / 64
    q = (np.pi * p.R_inner ** 2 * p.rhow + np.pi * (r_outer ** 2 - p.R_inner ** 2) * p.m['rho']) * p.g
    M = q * L ** 2 / 8

    strain_y = p.max_pres * r_outer / (h * Ey)
    strain_x = M * r_outer / (Ex * I)

    return strain_x, strain_y

def get_effective(layup):
    A = lam.computeA(layup)
    h = lam.laminateThickness(layup)
    Ex = (A[0,0] - A[0,1]/A[1,1])/h
    Ey = (A[1,1] - A[0,1]/A[0,0])/h
    return Ex, Ey

def get_load_prop_factor(stress):
    s1, s2, s12 = stress
    XT,YT,XC,YC,SL,ST = p.m['XT'], p.m['YT'], p.m['XC'], p.m['YC'], p.m['S12'], p.m['S23']

    fE_FF = max((s1/XT, -s1/XC))

    if s2 >= 0:
        fE_IFF = (s2/YT)**2 + (s12/ST)**2
    else: # s2 <0:
        fE_IFF = ((s2/(2 * ST))**2 + ( (YC/(2 * ST))**2 - 1) * (s2/YC) + (s12/ST)**2)

    R = 1 / np.array([fE_IFF, fE_FF])

    return min(R)

def check_failure(layup, L):
    global_strain = get_strains(layup, L)

    for i, layer in enumerate(layup):
        Te = lam.T2De(layer['ori'])
        layer_strain = np.dot(Te, global_strain)

        Q = lam.Q2D(layer['mat'])
        layer_stress = np.dot(Q, layer_strain)
        resistance = get_load_prop_factor(layer_stress)
        if resistance < 2.2:
            return True

    return False

# layup1 = [{'mat': p.m, 'ori': 85, 'thi': 10},
#           {'mat': p.m, 'ori': -85, 'thi': 10},
#           {'mat': p.m, 'ori': 15, 'thi': 5},
#           {'mat': p.m, 'ori': -15, 'thi': 5}]
#
# Len = 34000
# print('loads :', get_load(layup1, Len))
# print(get_strains(layup1, Len))
# print(check_failure(layup1, Len))