
import bpy
from mathutils import Matrix, Vector


def get_bone_size_factor(bone, ob, relative=True):
    world_box = [ob.matrix_world @ Vector(co) for co in ob.bound_box]

    height = (world_box[1]-world_box[0]).length
    depth = (world_box[3]-world_box[0]).length
    width = (world_box[4]-world_box[0]).length
    '''
    length = height
    if height < 0.001: 
        if depth > 0.001:
            length = depth
        elif width > 0.001:
            length = width
    '''
    length = max((height, depth, width))

    size_factor = 1 / length
    if relative:
        size_factor /= bone.bone.length
    
    return size_factor



def transform_matrix(loc=(0, 0, 0), rot=(0, 0, 0), scale=(1, 1, 1)):
    l_mat = Matrix.Translation(Vector(loc))

    rx_mat = Matrix.Rotation(rot[0], 4, 'X')
    ry_mat = Matrix.Rotation(rot[1], 4, 'Y')
    rz_mat =Matrix.Rotation(rot[2], 4, 'Z')

    r_mat = rz_mat @ ry_mat @ rx_mat

    sx_mat = Matrix.Scale(scale[0], 4, Vector((1,0,0)))
    sy_mat = Matrix.Scale(scale[1], 4, Vector((0,1,0)))
    sz_mat = Matrix.Scale(scale[2], 4, Vector((0,0,1)))

    s_mat = sx_mat @ sy_mat @ sz_mat

    return  l_mat @ r_mat @ s_mat

def get_bone_matrix(bone):
    bone_mat = bone.matrix
    if bone.custom_shape_transform:
        bone_mat = bone.custom_shape_transform.matrix 
        
    bone_mat = bone_mat @ transform_matrix(scale=(bone.bone.length,)*3)
    bone_mat = bone.id_data.matrix_world @ bone_mat

    return bone_mat

def apply_mat_to_verts(data, mat, coords=None):
    if coords is None:
        coords = [v.co for v in data.vertices]

    coords = [v for co in coords for v in mat @ co]
    data.vertices.foreach_set('co', coords)
    data.update()

def transform_mesh(data, loc, rot, scale, xz_scale, size, slide, coords=None):
    if coords is None:
        coords = [0]*len(data.vertices)*3
        data.vertices.foreach_get('co', coords)

    sx = scale[0] * size * xz_scale
    sy = scale[1] * size
    sz = scale[2] * size * xz_scale

    l_vec = loc + Vector((0, slide, 0))

    mat = transform_matrix(l_vec, rot, (sx, sy, sz))

    data.vertices.foreach_set('co', coords)
    data.transform(mat)
    #apply_mat_to_verts(data, mat, coords)

