#  ***** BEGIN GPL LICENSE BLOCK *****
#
#   Copyright (C) 2024 Ilia Kurochkin <brothermechanic@yandex.com>
#
#   Created by Ilia Kurochkin (brothermechanic)
#   contact:    brothermechanic@yandex.com
#
#   This is free software;
#   you can redistribute it and/or modify
#   it under the terms of the GNU General Public License
#   as published by the Free Software Foundation; either version 3
#   of the License, or (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program; if not, see <https://www.gnu.org/licenses/>.
#
#  ***** END GPL LICENSE BLOCK *****
#
# coding: utf-8
'''
DESCRIPTION.
Blender object transforms functions.
'''

__version__ = '0.3'

from mathutils import Matrix, Vector, Quaternion
import bpy


def apply_transforms(obj, location=False, rotation=False, scale=False):
    ''' bake local object transforms '''
    # original idea from https://github.com/machin3io/MACHIN3tools
    # update database
    bpy.context.view_layer.update()

    def get_loc_matrix(location):
        return Matrix.Translation(location)

    def get_rot_matrix(rotation):
        return rotation.to_matrix().to_4x4()

    def get_sca_matrix(scale):
        scene_scale_martix = Matrix()
        for i in range(3):
            scene_scale_martix[i][i] = scale[i]
        return scene_scale_martix

    if location and rotation and scale:
        loc, rot, sca = obj.matrix_world.decompose()
        mesh_martix = get_loc_matrix(loc) @ get_rot_matrix(
            rot) @ get_sca_matrix(sca)
        obj.data.transform(mesh_martix)
        apply_matrix = get_loc_matrix(Vector.Fill(3, 0)) @ get_rot_matrix(Quaternion()) @ get_sca_matrix(Vector.Fill(3, 1))
        obj.matrix_world = apply_matrix
    else:
        if location:
            raise Exception(
                'Location only applies with all transformations (rotate and scale) together!'
            )
        if rotation:
            loc, rot, sca = obj.matrix_world.decompose()
            mesh_martix = get_rot_matrix(rot)
            obj.data.transform(mesh_martix)
            apply_matrix = get_loc_matrix(loc) @ get_rot_matrix(Quaternion()) @ get_sca_matrix(sca)
            obj.matrix_world = apply_matrix

        if scale:
            loc, rot, sca = obj.matrix_world.decompose()
            mesh_martix = get_sca_matrix(sca)
            obj.data.transform(mesh_martix)
            apply_matrix = get_loc_matrix(loc) @ get_rot_matrix(rot) @ get_sca_matrix(Vector.Fill(3, 1))
            obj.matrix_world = apply_matrix

    obj.rotation_mode = 'XYZ'
    return obj


def round_transforms(obj):
    ''' Geting location of object and round it. '''
    for idx, axis in enumerate(obj.location[:]):
        obj.location[idx] = round(axis, 5)
    return obj.location
