#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
# ADD LICENSE SHORT INFORMATION HERE
#

"""
Cython version of rainflow counting algorithm.
This version is considerable faster than the Python equivalent but require compilation.
"""

# side-packages
import sys
sys.path.append("../modules")
from .common_impl import OccuranceCounter
#import numpy as np
cimport cython

# define authorship information
__authors__ = ['Thomas Nygårds']
__author__ = ','.join(__authors__)
__credits__ = []
__copyright__ = 'Copyright (c) 2020 MSC Software'
__license__ = ''

# maintenance information
__maintainer__ = 'Thomas Nygårds'
__email__ = 'thomas.nygards@mscsoftware.com'


# Notes to self:
#
# Decorator explanation:
# @cython.boundscheck(False):   Deactivate bounds checking, so make sure to stay in range!
# @cython.wraparound(False):    Deactivate negative indexing, so don't use negative indexes!
#
# cdef explanation:
# Py_ssize_t:   Efficient index type, use this for all index variables, but nothing else.
# int:          At least 16bit signed integer (many platforms use 32 bit today) ~ np.int32
# long:         At least 32bit signed integer (many platforms use 64 bit today) ~ np.int64
# long long:    At least 64bit signed integer (many platforms use 64 bit today) ~ np.int64
# float:        32bit floating point ~ np.float32
# double:       64bit floating point ~ np.float64
# long double:  80bit floating point ~ np.longdouble
#


cpdef double convert_real2(str val):
    ax = val.strip()
    if not ax:
        return 0.0
    return float(ax[0:1] + ax[1:].upper().replace('-', 'E-').replace('+', 'E+').replace('EE', 'E'))


#def convert_real2(val):
#    return c_convert_real2(val.encode('utf-8'))

cpdef process_ctetra(set BoltElList, set TopList, int cnt1, int cpid, int eflagtet, dict eltype, dict eqDict, list inl, str lin, dict matInteg,
                   dict pSolDict, str partName, dict pidname, dict tetFace, list tetId):
    cdef int corder
    cdef int tId
    cdef int g
    cdef list nl
    cdef list out_strs

    out_strs=[]
    if len(lin) > 60:
        torder = 2
    else:
        torder = 1
    if eflagtet == 1 or (cpid != int(lin[16:24])):
        cpid = int(lin[16:24])
        intAba = matInteg[pSolDict[cpid][0]]
        if intAba == 'cont':
            elSuffix = 'M'
            out_strs.append('** Modified formulation for contact selected from Material Description\n')
        elif intAba == 'inc':
            elSuffix = 'I'
            out_strs.append('** Improved stress formulation selected from Material Description\n')
        elif intAba == 'std':
            elSuffix = ''
            out_strs.append('** Full integration formulation selected from Material Description\n')
        else:
            elSuffix = ''
            out_strs.append('** Full integration formulation selected since Material Description is missing\n')
        partpid = '%s_PID_%i' % (partName, cpid)
        pidname[partpid] = [cpid, 'sol']
        if len(lin) > 60:
            out_strs.append('*ELEMENT, TYPE=C3D10%s, ELSET=%s\n' % (elSuffix, partpid))
        else:
            out_strs.append('*ELEMENT, TYPE=C3D4, ELSET=%s\n' % (partpid))
        eflagtet = 0
    tId = int(lin[8:16])
    eltype[tId] = 4
#    n1 = int(lin[24:32])
#    n2 = int(lin[32:40])
#    n3 = int(lin[40:48])
#    n4 = int(lin[48:56])
#    if torder == 2:
#        n5 = lin[56:64]
#        n6 = lin[64:72]
#        tId = int(lin[8:16])
#        lin = inl[cnt1]
#        cnt1 = cnt1 + 1
#        n7 = lin[8:16]
#        n8 = lin[16:24]
#        n9 = lin[24:32]
#        n10 = lin[32:40]
#        out_strs.append('%8i,%8i,%8i,%8i,%8i,%s,%s,%s,%s,%s,%s\n' % (
#            tId, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10))
#    else:
#        out_strs.append( '%8i,%8i,%8i,%8i,%8i\n' % (tId, n1, n2, n3, n4))
    nl = []
    nl.append(int(lin[24:32]))
    nl.append(int(lin[32:40]))
    nl.append(int(lin[40:48]))
    nl.append(int(lin[48:56]))
    g = 0
    while g < 4:
        if nl[g] in TopList:
            nl[g] = eqDict[nl[g]]
            BoltElList.add(tId)
        g = g + 1
    if torder == 2:
        nl.append(int(lin[56:64]))
        nl.append(int(lin[64:72]))
        tId = int(lin[8:16])
        lin = inl[cnt1]
        cnt1 = cnt1 + 1
        nl.append(int(lin[8:16]))
        nl.append(int(lin[16:24]))
        nl.append(int(lin[24:32]))
        nl.append(int(lin[32:40]))
        g = 4
        while g < 10:
            if nl[g] in TopList:
                nl[g] = eqDict[nl[g]]
                BoltElList.add(tId)
            g = g + 1
        out_strs.append('%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i\n' % (
            tId, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9]))
    else:
        out_strs.append( '%8i,%8i,%8i,%8i,%8i\n' % (tId, nl[0], nl[1], nl[2], nl[3]))
    


    tetFace[tId, 1] = [nl[0], nl[2], nl[1]]
    tetFace[tId, 2] = [nl[0], nl[1], nl[3]]
    tetFace[tId, 4] = [nl[0], nl[3], nl[2]]
    tetFace[tId, 3] = [nl[1], nl[2], nl[3]]

    tetId.append(tId)
    return cnt1, cpid, eflagtet, out_strs,tId, nl
    
    
cpdef process_chexa(set BoltElList, set TopList, int cnt1, int cpid, int eflaghex, dict eltype, dict eqDict, dict hexFace, list hexId, list inl, str lin,
                  dict matInteg, dict pSolDict, str partName, dict pidname):
# Stefan added try/except need to be taken care of
#    try:
#        eflaghex == 1
#    except:
#        print("Warning eflaghex not defined...setting it to zero")
#        eflaghex = 0
#    cdef int corder
    cdef int hId
    cdef int g
    cdef list nl
    cdef list out_strs
    lin3=inl[cnt1+1]
    if lin3[0:1] == ' ' or lin3[0:1] == '+' :
        horder=2
    else :
        horder=1

    out_strs=[]
    if eflaghex == 1 or (cpid != int(lin[16:24])):
        cpid = int(lin[16:24])
        intAba = matInteg[pSolDict[cpid][0]]
        if intAba == 'inc':
            elSuffix = 'I'
            out_strs.append('** Incomapatible modes formulation selected from Material Description\n')
        elif intAba == 'red':
            elSuffix = 'R'
            out_strs.append('** Reduced integration formulation selected from Material Description\n')
        elif intAba == 'std':
            elSuffix = ''
            out_strs.append('** Full integration formulation selected from Material Description\n')
        else:
            elSuffix = ''
            out_strs.append('** Full integration formulation selected since Material Description is missing\n')
        partpid = '%s_PID_%i' % (partName, cpid)
        pidname[partpid] = [cpid, 'sol']
        if horder == 1 :
            tmp = '*ELEMENT, TYPE=C3D8%s, ELSET=%s\n' % (elSuffix, partpid)
        else :
            tmp = '*ELEMENT, TYPE=C3D20%s, ELSET=%s\n' % (elSuffix, partpid)
        out_strs.append(tmp)
        eflaghex = 0
    nl = []
    nl.append(int(lin[24:32]))
    nl.append(int(lin[32:40]))
    nl.append(int(lin[40:48]))
    nl.append(int(lin[48:56]))
    nl.append(int(lin[56:64]))
    nl.append(int(lin[64:72]))
    hId = int(lin[8:16])
    hexId.append(hId)
    eltype[hId] = 6
    lin = inl[cnt1]
    cnt1 = cnt1 + 1
    nl.append(int(lin[8:16]))
    nl.append(int(lin[16:24]))
    g = 0
    while g < 8:
        if nl[g] in TopList:
            nl[g] = eqDict[nl[g]]
            BoltElList.add(hId)
        g = g + 1
    if horder == 2 :
        nl.append(int(lin[24:32]))
        nl.append(int(lin[32:40]))
        nl.append(int(lin[40:48]))
        nl.append(int(lin[48:56]))
        nl.append(int(lin[56:64]))
        nl.append(int(lin[64:72]))
        lin = inl[cnt1]
        cnt1 = cnt1 + 1
        nl.append(int(lin[8:16]))
        nl.append(int(lin[16:24]))
        nl.append(int(lin[24:32]))
        nl.append(int(lin[32:40]))
        nl.append(int(lin[40:48]))
        nl.append(int(lin[48:56]))
        g = 8
        while g < 20:
            if nl[g] in TopList:
                nl[g] = eqDict[nl[g]]
                BoltElList.add(hId)
            g = g + 1
        tmp = '%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,\n%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i\n' % (
            hId, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7], nl[8], nl[9], nl[10], nl[11],
            nl[16], nl[17], nl[18], nl[19], nl[12], nl[13], nl[14], nl[15])
    else :
        tmp = '%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i,%8i\n' % (
        hId, nl[0], nl[1], nl[2], nl[3], nl[4], nl[5], nl[6], nl[7])
    out_strs.append(tmp)
    hexFace[hId, 1] = [nl[0], nl[3], nl[2], nl[1]]
    hexFace[hId, 3] = [nl[0], nl[1], nl[5], nl[4]]
    hexFace[hId, 6] = [nl[0], nl[4], nl[7], nl[3]]
    hexFace[hId, 4] = [nl[1], nl[2], nl[6], nl[5]]
    hexFace[hId, 5] = [nl[2], nl[3], nl[6], nl[7]]
    hexFace[hId, 2] = [nl[4], nl[5], nl[6], nl[7]]
    return cnt1, cpid, hId, out_strs, eflaghex, nl

def process_cquad4(int cpid, int eflagq, dict eltype, str lin, dict matInteg, dict pShlDict, str partName, dict pidname):
    cdef list out_strs
    out_strs=[]
    if eflagq == 1 or (cpid != int(lin[16:24])):
        cpid = int(lin[16:24])
        intAba = matInteg[pShlDict[cpid][0]]
        if intAba == 'red':
            elSuffix = 'R'
            out_strs.append('** Reduced integration formulation selected from Material Description\n')
        elif intAba == 'std':
            elSuffix = ''
            out_strs.append('** Full integration formulation selected from Material Description\n')
        else:
            elSuffix = ''
            out_strs.append('** Full integration formulation selected since Material Description is missing\n')
        partpid = '%s_PID_%i' % (partName, cpid)
        pidname[partpid] = [cpid, 'shell']
        tmp = '*ELEMENT, TYPE=S4%s, ELSET=%s\n' % (elSuffix, partpid)
        out_strs.append(tmp)
        eflagq = 0
    tmp = '%8i,%8i,%8i,%8i,%8i\n' % (
        int(lin[8:16]), int(lin[24:32]), int(lin[32:40]), int(lin[40:48]), int(lin[48:56]))
    out_strs.append(tmp)
    eltype[int(lin[8:16])] = 1
    return cpid, eflagq, out_strs

