#ifndef PW_SCENE_TRANSFORM_HPP
#define PW_SCENE_TRANSFORM_HPP

#include <pw/core/matrix.hpp>
#include <pw/core/quaternion.hpp>
#include <pw/core/vector.hpp>

namespace pw {

struct transform {

    transform() = default;
    transform(const transform&) = default;

	inline const matrix4x4& local() const { return _local; }
    void set_local(const matrix4x4 &local)
    {
        _local = local;
    }

	inline const matrix4x4& global() const { return _global; }

    void set_global(const matrix4x4 &global)
    {
        matrix4x4 diff = _global.inverse() * global;
        _local = _local * diff;

        _global = global;
    }

	inline transform& translate(const real_t &x, const real_t &y, const real_t &z) {
        _local(0,3) += x;_local(1,3) += y;_local(2,3) += z;
		return *this;
	}

	inline transform& set_translation(const real_t &x, const real_t &y, const real_t &z) {
		_local(0,3) = x;_local(1,3) = y;_local(2,3) = z;
		return *this;
	}

	inline transform& rotate(const quaternion& q) {
        _local = _local * q.to_matrix();
		return *this;
	}

	inline transform& set_rotation(const quaternion& q) {
		_local = q.to_matrix();
		return *this;
	}

	inline transform& scale(const real_t &sx, const real_t &sy, const real_t &sz) {
		_local(0,0) *= sx; _local(1,1) *= sy; _local(2,2) *= sz;
		return *this;
	}

	inline transform& set_scale(const real_t &sx, const real_t &sy, const real_t &sz) {
		_local(0,0) = sx; _local(1,1) = sy; _local(2,2) = sz;
		return *this;
	}

	inline transform& scale(const real_t& uniform_scale) {
		return scale(uniform_scale,uniform_scale,uniform_scale);
	}

    matrix4x4 _local = matrix4x4::identity();
    matrix4x4 _global = matrix4x4::identity();
};

}

#endif
