MooImage=new Class({
    
    options:{
        rotate: 0,
        centerX: 0,
        centerY: 0,
        left: 0,
        top: 0,
        skewX: 0,
        skewY: 0,
        flipX: 0,
        flipY: 0,
        autoExpand: true,
		container: document.body
    },
    
    initialize: function(src,options){
        this.src=src;
        this.setOptions(options);
        this.createImg();
        //return this.img;
    },
    
    createImg: function(){
        if(window.ie){
            this.createImgIE();
            return;
        }
        var svgns='http://www.w3.org/2000/svg';
        var svg=document.createElementNS(svgns,'svg');
        this.svg=svg;
        svg.style.position='relative';

        this.options.container.appendChild(svg);
        var image=document.createElementNS(svgns,'image');
        this.img=image;
        svg.appendChild(image);

        var img=new Asset.image(this.src, {
			onload: function(){
				if(window.webkit){
	                this.naturalWidth=parseInt(this.options.naturalWidth) || 64;
	                this.naturalHeight=parseInt(this.options.naturalHeight) || 64;
	            }else{
					this.naturalWidth=img.width;
					this.naturalHeight=img.height;
				}
	            image.setAttributeNS("http://www.w3.org/1999/xlink", "href", this.src);
	            image.setAttribute('width',this.naturalWidth);
	            image.setAttribute('height',this.naturalHeight);

	            this.transform();  
			}.bind(this)
		});                     
    },
    
    createImgIE: function(){
        this.initVML();
        var img=new Element('v:image');
        this.img=img;
        img.src=this.src;
        img.injectInside(this.options.container);
        img.setStyle('position','relative');
        this.transform();
    },
    
    initVML: function(){
        if(!window.$initVML){
            document.namespaces.add("v", "urn:schemas-microsoft-com:vml");
            document.createStyleSheet().cssText="v\\:*{behavior:url(#default#VML)}";
        }
        window.$initVML=true;
    },
    
    transform: function(options){
        options=$merge(this.options,options);
        this.options=options;
        this.flipX=this.options.flipX.toInt() || 0;
        this.flipY=this.options.flipY.toInt() || 0;
        var tan=this.tan;
        var cos=this.cos;
        var sin=this.sin;
        var a=options.skewX.toInt();
        var b=options.skewY.toInt();
        var rot=options.rotate;

        this.M11 = cos(rot)+tan(b)*sin(rot);
        this.M12 = -sin(rot)+cos(rot)*tan(b);
        this.M21 = cos(rot)*tan(a)+sin(rot)+sin(rot)*tan(a)*tan(b);
        this.M22 = -sin(rot)*tan(a)+cos(rot)+cos(rot)*tan(a)*tan(b);
        if(window.ie){
            this.transformIE(options);
            return;
        }
        
        var signX=this.signX=(1-2*this.flipX);
        var signY=this.signY=(1-2*this.flipY);

        var width=options.width.toInt()/this.naturalWidth;
        var height=options.height.toInt()/this.naturalHeight;       

        this.M11 = signX*this.M11;
        this.M12 = signX*this.M12;
        this.M21 = signY*this.M21;
        this.M22 = signY*this.M22;

        this.getdz();
        var dx=this.dz[0];
        var dy=this.dz[1];

        if(this.options.autoExpand){
            
            this.getMinMax();
            var left=options.left.toInt()-this.MinMax.min[0]-dx;
            var top=options.top.toInt()-this.MinMax.min[1]-dy;

            var svg=this.svg;
            svg.style.left=this.MinMax.min[0].toInt()+(2*this.options.centerX.toFloat()-1)*this.options.width.toInt()*this.flipX+'px';
            svg.style.top=this.MinMax.min[1].toInt()+(2*this.options.centerY.toFloat()-1)*this.options.height.toInt()*this.flipY+'px';

            svg.setAttribute('width',this.MinMax.max[0]-this.MinMax.min[0]+20);
            svg.setAttribute('height',this.MinMax.max[1]-this.MinMax.min[1]+20);
        }else{
            var left=options.left.toInt()-dx+5000;
            var top=options.top.toInt()-dy+5000;
            
            var svg=this.svg;
            svg.style.left=-5000+(2*this.options.centerX.toFloat()-1)*this.options.width.toInt()*this.flipX+'px';
            svg.style.top=-5000+(2*this.options.centerY.toFloat()-1)*this.options.height.toInt()*this.flipY+'px';

            svg.setAttribute('width',5000+window.getWidth()-this.options.container.getLeft()-(2*this.options.centerX.toFloat()-1)*this.options.width.toInt()*this.flipX);
            svg.setAttribute('height',5000+window.getScrollHeight()-this.options.container.getTop()-(2*this.options.centerY.toFloat()-1)*this.options.height.toInt()*this.flipY);
        }

        if(window.webkit){
        left-=svg.style.left.toInt();
        top-=svg.style.top.toInt();
        }

        this.img.setAttribute("transform", 
        "translate("+left+","+top+")"+
        "matrix("+
        this.M11+","+
        this.M12+","+
        this.M21+","+
        this.M22+",0,0)"+
        "scale("+width+" "+height+") "
        );
                         
    },
    
    transformIE: function(options){
        var img=this.img;
        
        this.getdz();
        this.getMinMax();
        
        img.setStyles({
            left: this.MinMax.min[0],
            top: this.MinMax.min[1]
        });

        img.setStyles({
            width: options.width.toInt(),
            height: options.height.toInt()
        });
        var flip='';
        if(this.flipX){
            flip+='x ';
        }
        if(this.flipY){
            flip+='y';
        }
        img.style.flip=flip;
        
        var tan=this.tan;
        var cos=this.cos;
        var sin=this.sin;
        var a=options.skewX.toInt();
        var b=options.skewY.toInt();
        var rot=options.rotate;
        img.style.filter="progid:DXImageTransform.Microsoft.Matrix(sizingmethod='auto expand')";
        img.filters.item(0).M11 = cos(rot)+tan(b)*sin(rot);
        img.filters.item(0).M12 = tan(a)*cos(rot)+sin(rot)+sin(rot)*tan(a)*tan(b);
        img.filters.item(0).M21 = -sin(rot)+tan(b)*cos(rot);
        img.filters.item(0).M22 = -tan(a)*sin(rot)+cos(rot)+cos(rot)*tan(a)*tan(b);
    },
    
    cos: function(a){//a=[0,360]
        return Math.cos(Math.PI/180*a);
    },
    
    sin: function(a){
        return Math.sin(Math.PI/180*a);
    },
    
    tan: function(a){
        return Math.tan(Math.PI/180*a);
    },
       
    getQuadCoords: function(){
        var o=this.options;
        var left=o.left.toInt();
        var top=o.top.toInt();
        var right=left+o.width.toInt();
        var bottom=top+o.height.toInt();
        quad=[
        [left,top],
        [left,bottom],
        [right,top],
        [right,bottom]
        ];

        return quad;
    },
        
    skewrot: function(x,y){
        var x=x-this.options.left.toInt();
        var y=y-this.options.top.toInt();
        
        return [this.M11*x+this.M21*y,
        this.M12*x+this.M22*y];
    },
    
    getQuadCoordsAfterSkewRot: function(){
        var quad=this.getQuadCoords();
        
        dx=this.dz[0];dy=this.dz[1];
     
        for(var i=4;i--;){
            var skewrotQuad=this.skewrot(quad[i][0],quad[i][1]);
            quad[i][0]=skewrotQuad[0]+this.options.left.toInt()-dx;
            quad[i][1]=skewrotQuad[1]+this.options.top.toInt()-dy;
        }

        return quad;
    },
    
    getdz: function(){
        if(!window.ie){
            var dx_old=(this.flipX+this.options.centerX.toFloat()*this.signX)*this.options.width.toInt();
            var dy_old=(this.flipY+this.options.centerY.toFloat()*this.signY)*this.options.height.toInt();
        }else{
            var dx_old=this.options.centerX*this.options.width.toInt();
            var dy_old=this.options.centerY*this.options.height.toInt();
        }
            
        dx=this.M11*dx_old+this.M21*dy_old-dx_old;
        dy=this.M12*dx_old+this.M22*dy_old-dy_old;
        this.dz=[dx,dy];
        return;
    },
    
 
    getMinMax: function(){
        var quad=this.getQuadCoordsAfterSkewRot();

        var minx=Math.min(quad[0][0],quad[1][0],quad[2][0],quad[3][0]);
        var miny=Math.min(quad[0][1],quad[1][1],quad[2][1],quad[3][1]);
        var maxx=Math.max(quad[0][0],quad[1][0],quad[2][0],quad[3][0]);
        var maxy=Math.max(quad[0][1],quad[1][1],quad[2][1],quad[3][1]);
        this.MinMax={
        min: [minx, miny],
        max: [maxx, maxy]
        };
        return;
    }
    
});

MooImage.implement(new Options);

