var Smallthing = Smallthing || {};

__createTweenPosition = function(p)
{
    return GAME.Tween.get(object.position, p);
};

__createTweenRotation = function(p)
{
    return GAME.Tween.get(object.rotation, p);
};

__setVisible = function(e)
{
    this.visible = e;
    for(var i in this.chidren)
    {
        var child = this.children[i];
        if(child != null)
        {
            child.visible = e;
        }
    }
}

__getVisible = function()
{
    return this.visible;
}

__getPosition = function()
{
    return this.position;
}

__setPosition = function(x, y, z)
{
    if(x.x != null)
    {
        this._position.x = x.x;
        this._position.y = x.y;
        this._position.z = x.z;
        return;
    }
    this._position.x = x;
    this._position.y = y;
    this._position.z = z;

    this.onUpdate(0);
}

__setPositionLocal = function(x, y, z)
{
    if(x.x != null)
    {
        this._positionLocal.x = x.x;
        this._positionLocal.y = x.y;
        this._positionLocal.z = x.z;
        return;
    }
    this._positionLocal.x = x;
    this._positionLocal.y = y;
    this._positionLocal.z = z;

    this.onUpdate(0);
}

__setRotation = function(x, y, z)
{
    if(x.x != null)
    {
        this._rotation.x = x.x;
        this._rotation.y = x.y;
        this._rotation.z = x.z;
        return;
    }
    this._rotation.x = x;
    this._rotation.y = y;
    this._rotation.z = z;

    this.onUpdate(0);
}

__setRotationLocal = function(x, y, z)
{
    if(x.x != null)
    {
        this._rotationLocal.x = x.x;
        this._rotationLocal.y = x.y;
        this._rotationLocal.z = x.z;
        return;
    }
    this._rotationLocal.x = x;
    this._rotationLocal.y = y;
    this._rotationLocal.z = z;

    this.onUpdate(0);
}

__setScale = function(x, y, z)
{
    if(x.x != null)
    {
        this._scale.x = x.x;
        this._scale.y = x.y;
        this._scale.z = x.z;
        return;
    }
    this._scale.x = x;
    this._scale.y = y;
    this._scale.z = z;

    this.onUpdate(0);
}

__setScaleLocal = function(x, y, z)
{
    if(x.x != null)
    {
        this._scaleLocal.x = x.x;
        this._scaleLocal.y = x.y;
        this._scaleLocal.z = x.z;
        return;
    }
    this._scaleLocal.x = x;
    this._scaleLocal.y = y;
    this._scaleLocal.z = z;

    this.onUpdate(0);
}

__onUpdate = function(dtime)
{
    if(this.disableUpdate)
        return;

    if(this.type === 'Bone')
        return;

    if(this.type === 'SkinnedMesh')
        return;

    if(!this.visible)
        return;

    if(this.animation_mixer == null && this.type !== 'Group' && this.type !== 'Scene') 
    {

        var xform = new THREE.Matrix4();
        xform.identity();

        var T = new THREE.Matrix4();        T.identity();
        var R = new THREE.Matrix4();        R.identity();
        var Rx = new THREE.Matrix4();        Rx.identity();
        var Ry = new THREE.Matrix4();        Ry.identity();
        var Rz = new THREE.Matrix4();        Rz.identity();
        var S = new THREE.Matrix4();        S.identity();

        T.makeTranslation(this._position.x + this.animations.position.x + this._positionLocal.x, 
                        this._position.y + this.animations.position.y + this._positionLocal.y, 
                        this._position.z + this.animations.position.z + this._positionLocal.z);

        S.makeScale(this._scale.x * this.animations.scale.x * this._scaleLocal.x, 
                this._scale.y * this.animations.scale.y * this._scaleLocal.y,
                this._scale.z * this.animations.scale.z * this._scaleLocal.z);

        if(this.isAnimated != null){
            Rx.makeRotationX(Smallthing.MyMath.degrees_to_radians(this._rotation.x + this.animations.rotation.x+this._rotationLocal.x+90));
        }
        else {
            Rx.makeRotationX(Smallthing.MyMath.degrees_to_radians(this._rotation.x + this.animations.rotation.x+this._rotationLocal.x));
        }
        Ry.makeRotationY(Smallthing.MyMath.degrees_to_radians(this._rotation.y + this.animations.rotation.y+this._rotationLocal.y));
        Rz.makeRotationZ(Smallthing.MyMath.degrees_to_radians(this._rotation.z + this.animations.rotation.z+this._rotationLocal.z));

        R.multiply(Rx);
        R.multiply(Ry);
        R.multiply(Rz);

        xform.multiply(T);
        xform.multiply(R);
        xform.multiply(S);

        this.matrix = xform;
        this.matrixAutoUpdate = false;
    }
    else 
    {
        this.position.x = this._position.x + this.animations.position.x + this._positionLocal.x;
        this.position.y = this._position.y + this.animations.position.y + this._positionLocal.y;
        this.position.z = this._position.z + this.animations.position.z + this._positionLocal.z;

        this.scale.x = this._scale.x * this.animations.scale.x * this._scaleLocal.x;
        this.scale.y = this._scale.y * this.animations.scale.y * this._scaleLocal.y;
        this.scale.z = this._scale.z * this.animations.scale.z * this._scaleLocal.z;

        this.rotation.x = Smallthing.MyMath.degrees_to_radians(this._rotation.x + this.animations.rotation.x + this._rotationLocal.x);
        this.rotation.y = Smallthing.MyMath.degrees_to_radians(this._rotation.y + this.animations.rotation.y + this._rotationLocal.y);
        this.rotation.z = Smallthing.MyMath.degrees_to_radians(this._rotation.z + this.animations.rotation.z + this._rotationLocal.z);
    }

    if(this.callbackUpdate != null)
    {
        this.callbackUpdate(dtime);
    }

    if(this.materials != null)
    {
        for(var i in this.materials)
        {
            var mtl = this.materials[i];
            mtl.opacity = this.alpha;
        }
    }

    if(this.material != null)
    {
        this.material.opacity = this.alpha;
    }

    if(this.animation_mixer != null)
    {
        this.animation_mixer.update(dtime);
    }
}

addCommon = function(object3d)
{
    if(object3d == null)
    {
        return;
    }

    for(var i in object3d.children)
    {
        var child = object3d.children[i];
        Common3D_set(child);
    }
}

Common3D_set = function(o)
{
    if(typeof o === 'undefined')
        return;
        
    o.__internal_id = __OBJECT_ID++;

    o.alpha = 1.0;

    o._position = new THREE.Vector3(0,0,0);
    o._scale = new THREE.Vector3(1,1,1);
    o._rotation  = new THREE.Vector3(0,0,0);

    o._positionLocal = new THREE.Vector3(0,0,0);
    o._scaleLocal = new THREE.Vector3(1,1,1);
    o._rotationLocal  = new THREE.Vector3(0,0,0);

    o.createTweenPosition = __createTweenPosition;
    o.createTweenRotation = __createTweenRotation;

    o.setPosition = __setPosition;
    o.setPositionLocal = __setPositionLocal;
    o.getPosition = __getPosition;

    o.setVisible = __setVisible;
    o.getVisible = __getVisible;

    o.setRotation = __setRotation;
    o.setRotationLocal = __setRotationLocal;
    
    o.setScale = __setScale;
    o.setScaleLocal = __setScaleLocal;

    o.onUpdate = __onUpdate;

    o.disableUpdate = false;

    o.animations = {position:new THREE.Vector3(0,0,0), scale:new THREE.Vector3(1,1,1), rotation:new THREE.Vector3(0,0,0)};

    o.enableOpacity = function()
    {
        if(o.materials != null)
        {
            for(var i in o.materials)
            {
                var mtl = o.materials[i];
                mtl.transparent = true;
                o.receiveShadow = false;
            }
        }
        if(o.material != null)
        {
            o.material.transparent = true;
        }
    }

    o.disableOpacity = function()
    {
        if(o.materials != null)
        {
            for(var i in o.materials)
            {
                var mtl = o.materials[i];
                mtl.transparent = false;
            }
        }
        if(o.material != null)
        {
            o.material.transparent = false;
        }        
    }

    o.createTweenAnimPosition = function(loop, v)
    {
        if(v != null)
            this.animations.position = {x:v.x, y:v.y, z:v.z};

        return GAME.Tween.get(this.animations.position, {loop:loop});
    }

    o.createTweenAnimScale = function(loop, v)
    {
        if(v != null)
            this.animations.scale = {x:v.x, y:v.y};
        
        return GAME.Tween.get(this.animations.scale, {loop:loop});
    }

    o.createTweenAnimAlpha = function(loop, v)
    {
        if(v != null)
            this.animations.alpha = {value:v};
        
        return GAME.Tween.get(this.animations.alpha, {loop:loop});
    }

    o.createTweenAnimAngle = function(loop, v)
    {
        if(v != null)
            this.animations.rotation = {x:v.x, y:v.y};
        
        return GAME.Tween.get(this.animations.rotation, {loop:loop});
    }

    o.removeAnimTweens = function()
    {
        GAME.Tween.removeTweens(this.animations.angle);
        GAME.Tween.removeTweens(this.animations.alpha);
        GAME.Tween.removeTweens(this.animations.scale);
        GAME.Tween.removeTweens(this.animations.position);
    }

    o.enableShadowCast = function()
    {
        this.traverse( function(child) {

            if(child != null && child.isMesh)
            {
                child.castShadow = true;
            }
        });
    }

    o.disableShadowCast = function()
    {
        this.traverse( function(child) {

            if(child != null && child.isMesh)
            {
                child.castShadow = false;
            }
        });
    }

    o.enableReceiveShadow = function()
    {
        this.traverse( function(child) {

            if(child != null && child.isMesh && !child.material.transparent)
            {
                child.receiveShadow = true;
/*
                if(child.material.transparent) {
                    console.warn('is not possible enable shadow receive for transparent object');
                    child.receiveShadow = false;
                }
                else {
                    child.receiveShadow = true;
                }
*/                
            }
        });        
    }

    o.disableReceiveShadow = function()
    {
        this.traverse( function(child) {

            if(child != null && child.isMesh)
            {
                child.receiveShadow = false;
            }
        });        
    }
    
    o.getObjectByName = function(name)
    {
        // hide every locators
        for(var i in o.children)
        {
            var child = o.children[i];
            if(child != null && child.name != null && child.name === name)
            {
                return child;
            }
        }           
         
        return null;
    }

    // hide every locators
    for(var i in o.children)
    {
        var child = o.children[i];
        if(child != null)
        {
            var name = child.name.toLowerCase();
            if(name.includes('_loc_') || name.includes('collider'))
            {
                child.visible = false;
            }
        }
    }    

    // set data from original data
    if(o.position != null)
        o.setPosition(o.position);
    if(o.scale != null)
        o.setScale(o.scale);
    if(o.rotation != null)
        o.setRotation(o.rotation);

    //if(o.type !== 'Scene' && o.type !== 'Group' && o.type !== 'SkinnedMesh' && o.type !== 'Mesh' && o.type !== 'Bone')
    if(o.type !== 'Scene' && o.type !== 'SkinnedMesh' && o.type !== 'Bone')
        OBJECTMANAGER.push(o);

    addCommon(o);
}
