/**                                                                    
 * BASIS SEON                                                          
 * Interface bsVader                                                   
 * Tags []                                                             
 * Requires: bsGUI.js, raphael.js, jQuery, json2.js, моск, базовая аналитическая геометрия                      
 *                                                           (школьный курс геометрии)      
 * клиент-интерфейс модуля Vader                                       
 *                                                                     
 * @author  Dmitry Balchugov <zibder(at)gmail(dot)com>
 * @author  Andrew (mas) Morozov <morozov(dot)mas(at)gmail(dot)com>                     
 * @version 0.3 2010-07-07                                             
 * @copyright Copyright (c) Dmitry Balchugov, Andrew (mas) Morozov 2005-2010,                
 *                                     (http://www.robonet.ru/)   
 * @licence See http://www.robonet.ru/basis/licence for details        
 *                                                                     
 * vim: set expandtab tabstop=4 shiftwidth=4:                          
 */

/*
          _________
          III| |III
        IIIII| |IIIII
       IIIIII| |IIIIII            _______________________
       IIIIII| |IIIIII            |                      |
      IIIIIII| |IIIIIII           |    A-hah-ha-ha-ha!   |
      IIIIIII\ /IIIIIII           |                      |
     II (___)| |(___) II          ~~~~~~~~~~~~~~~~~~~~~~~~
    II  \    /D\    /  II
   II  \ \  /| |\  / /  II        (и всё же не так страшно)
  II    \_\/|| ||\/_/    II
 II     / O-------O \     II
II_____/   \|||||/   \_____II
      /               \
      |_______________| <- Dart Vader

*/

function bsVader(){
        var info       = "BASIS Vader Controller";
        this.sMsgLoading=sMsgLoading;
        var sMsgLoading=bsGUIGetLoaderElement();
        this.sMsgComplete=sMsgComplete;
        var sMsgComplete='<span>Готово</span>';        
        
        /* main */
        this.aData=aData;
        var aData={};
        this.index=index;
        var index=0;

        this.hRaphael=hRaphael;
        var hRaphael=null;

        aData['obj_cnt']=0;             /* objects count */
        aData['cw']=12;                 /* control button width */
        aData['cw2']=(aData['cw'] / 2); /* a half of control button width */
        aData['cbc']='';                /* close button */
        aData['cbr']='';                /* resize button */
        aData['rbr']='';                /* rotate button */
        aData['cgc']='#999999';         /* gizmo stroke color */
        aData['dat']={};
        aData['hnd']={};
        
    /** 
     * init
     *
     * конструктор
     * инициализирует структуры
     *
     * @access public
     * @return void
     */
    this.init=init;
    function init(sel,w,h,a){

        if( typeof(w)=='undefined' ) {
            var w = $('#'+sel).css('width');
        }
        if( typeof(h)=='undefined' ) {
            var h = $('#'+sel).css('height');
        }

        hRaphael=Raphael(sel, w, h);
        aData['r']=hRaphael;
        /*if( a!=null ) {            
            for( key in a ) {
                aData[key]=a[key]);
            }
        }*/
    }

   /** 
     * getRaphael
     *
     * @access public
     * @return void
     */
    this.getRaphael=getRaphael;
    function getRaphael(){
        return hRaphael;
    }

   /** 
     * set
     *
     * @access public
     * @return void
     */
    this.set=set;
    function set(key, value){
        if( key!=null && value!=null ) {
            aData[key]=value;
        }
        return true;
    }


	this.fillData=fillData;
	function fillData(index,type,o,x,y,a){
        aData['dat'][index]={};
        aData['dat'][index]['type']     = type;
        aData['dat'][index]['fs']       = null;
        aData['dat'][index]['ff']       = null;
        aData['dat'][index]['text']     = null;
        aData['dat'][index]['color']    = null;
        aData['dat'][index]['w']        = o.getBBox().width;
        aData['dat'][index]['h']        = o.getBBox().height;
		aData['dat'][index]['maxsz'] 	= 0;
        aData['dat'][index]['ar']       = aData['dat'][index]['w']/aData['dat'][index]['h'];
        aData['dat'][index]['visible']  = true;
        aData['dat'][index]['res']      = true;
        aData['dat'][index]['clo']      = true;
        aData['dat'][index]['rot']      = true;
		aData['dat'][index]['cx'] 		= x + aData['dat'][index]['w']/2;
		aData['dat'][index]['cy'] 		= y + aData['dat'][index]['h']/2;
		aData['dat'][index]['scale'] 	= 1;
		aData['dat'][index]['alpha'] 	= a;
        aData['hnd'][index]={};
        aData['hnd'][index]['obj']      = o;
	}
	
    /** 
     * addText
     *
     * @access public
     * @return void
     */
    this.addText=addText;
    function addText(text,x,y,ff,fs,fc,a){
        if( a==null ) { a=0; }
        if( x==null ) { var x=10; }
        if( y==null ) { var y=10; }

        var o=hRaphael.text(0, 0, text).attr({
            'font-family': ff,
            'font-size':fs, 
            'opacity': 1.0,
            'fill': fc,
            'x':x,
            'y':y
        });
        
        index=Math.random(); 
        
        fillData( index, 'text', o, x,y,a );
        aData['dat'][index]['fs']       = fs;
        aData['dat'][index]['ff']       = ff;
        aData['dat'][index]['text']     = text;
        aData['dat'][index]['color']    = fc;
        aData['dat'][index]['uri']      = null;
        
        addGizmo(index);
    }

    /** 
     * addImage
     *
     * @access public
     * @return void
     */
    this.addImage=addImage;
    function addImage(uri,x,y,w,h,a,wmax,hmax){
        if( a==null ) { a=0; }
        if( uri==null ) { return false; }
        if( x==null ) { var x=10; }
        if( y==null ) { var y=10; }
        if( w==null ) { var w=80; }
        if( h==null ) { var h=80; }
        if( wmax==null ) { var wmax=w; }
        if( hmax==null ) { var hmax=h; }
		
		if( w>wmax ) w=wmax;
		if( h>hmax ) h=hmax;
        
		var o =  hRaphael.image(uri,x,y,w,h);
		        
        index=Math.random();

        fillData( index, 'image', o, x,y,a );
        aData['dat'][index]['uri']      = uri;
		aData['dat'][index]['maxsz']	= Math.sqrt(wmax*wmax + hmax*hmax)/2;

        addGizmo(index);
    }

      /** 
     * addImage
     *
     * @access public
     * @return void
     */
    this.addRect=addRect;
    function addRect(x,y,w,h,a){
        if( a==null ) { a=0; }
        if( x==null ) { var x=10; }
        if( y==null ) { var y=10; }
        if( w==null ) { var w=80; }
        if( h==null ) { var h=80; }
        
		var o =  hRaphael.rect(x,y,w,h);
        
        index=Math.random();

        fillData( index, 'rect', o, x,y,a );
        aData['dat'][index]['uri']      = '';

        addGizmo(index);
    }

	this.transpose = transpose;
	function transpose( x,y, ox,oy,alpha ) { with(Math){
		alpha = alpha*PI/180; 
		cosalpha = cos(alpha); sinalpha = sin(alpha);
		x1 = ox + x*cosalpha-y*sinalpha;
		y1 = oy + y*cosalpha+x*sinalpha;
		return {cx:x1,cy:y1};
	}}

    this.posGizmo=posGizmo;
	function posGizmo(i,cx,cy,scale,alpha) {
		cw2 = aData['cw2'];
		var pos;
		w0 = aData['dat'][i]['w'];	h0 = aData['dat'][i]['h'];
		w  = w0*scale;				h  = h0*scale;
		w2 = w/2;					h2 = h/2;
		if( aData['dat'][i]['type']=='text' ) {
			pos = { x:cx, y:cy };
			pos['font-size'] = aData['dat'][i]['fs']*scale;
		} else
			pos = { x:cx-w2, y:cy-h2 };
		pos.width  = w0*scale;
		pos.height = h0*scale;
		pos.rotation = alpha;
		/* object */
		aData['hnd'][i]['obj'].attr(pos);
		/* rect */
		pos.x = cx-w2; pos.y = cy-h2;
		aData['hnd'][i]['g'].attr(pos);
		/* delete marker */
		pos = transpose( +w2,-h2, cx,cy,alpha );
		aData['hnd'][i]['gcl'].attr({ x:pos.cx-cw2, y:pos.cy-cw2, rotation:alpha });
		/* resize marker */
		if( aData['dat'][i]['res'] ) {
			pos = transpose( +w2,+h2, cx,cy,alpha );
			aData['hnd'][i]['grs'].attr({ x:pos.cx-cw2, y:pos.cy-cw2, rotation:alpha });
		}
		/* rotate marker */
		if( aData['dat'][i]['rot'] ) {
			pos = transpose( -w2,+h2, cx,cy,alpha );
			aData['hnd'][i]['gro'].attr(pos);
		}
	}
	
	/** 
     * addGizmo
     *
     * @access public
     * @return void
     */
    this.addGizmo=addGizmo;
    function addGizmo(i){
        
        aData['obj_cnt']++;
        aData['hnd'][i]['obj'].attr({cursor: "move" });
        aData['hnd'][i]['obj'].node.setAttribute('id','obj_'+i);
 
        /* serv offsets */
        if( aData['dat'][i]['type'] == 'text' ) {
            aData['dat'][i]['ax']=0;//(aData['dat'][i]['w']/2);
            aData['dat'][i]['ay']=0;//(aData['dat'][i]['h']/2);

            var ox=aData['dat'][i]['x']+aData['dat'][i]['w']/2;
            var oy=aData['dat'][i]['y']+aData['dat'][i]['h']/2;

            if( typeof(ox)!='undefined' && typeof(oy)!='undefined' ) {
                if( !isNaN(ox) && !isNaN(ox)) {
                    aData['hnd'][i]['obj'].attr({
                        'x':ox,
                        'y':oy
                    });
                }               
            }
            
        }else{
            aData['dat'][i]['ax']=0;
            aData['dat'][i]['ay']=0;
        }
        var ax = aData['dat'][i]['ax'];
        var ay = aData['dat'][i]['ay'];
        
		var w  = aData['dat'][i]['w'];
        var h  = aData['dat'][i]['h'];
		var cx = aData.dat[i].cx;
		var cy = aData.dat[i].cy;
        var x  = cx - w/2;
		var y  = cy - h/2;
		var alpha = aData['dat'][i]['alpha'];
        
        /* gizmos */
        if( aData['cgc']==null || aData['cgc']=='' ) {
            var color='#999999';
        }else{
            var color=aData['cgc'];
        }

        aData['hnd'][i]['g']=aData['r'].rect(x-aData['cw2'],y-aData['cw2'],w+aData['cw'],h+aData['cw'],0);
        aData['hnd'][i]['g'].attr({'fill': color, 'stroke': color,'stroke-width': 1,'stroke-dasharray':"- ",cursor: "move",'fill-opacity': 0,'opacity':1});
        aData['hnd'][i]['g'].node.setAttribute('id','g_'+i);

        /* resize */
        if( aData['dat'][i]['res'] ) {
            if( aData['cbr']==null || aData['cbr']=='' ) {
                aData['hnd'][i]['grs']=aData['r'].rect(x+w+ax,y+h+ay,aData['cw'],aData['cw'],0);
                aData['hnd'][i]['grs'].attr({'fill': color, 'stroke': color,'stroke-width':1,cursor: "se-resize",'fill-opacity': 1,'opacity':1});
            }else{
                aData['hnd'][i]['grs']=aData['r'].image(aData['cbr'],  x+w+ax, y+h+ay, aData['cw'],aData['cw']);
            }
            aData['hnd'][i]['grs'].node.setAttribute('id','grs_'+i);
        }

        /* rotate */
        if( aData['dat'][i]['rot'] ) {
            if( aData['rbr']==null || aData['rbr']=='' ) {
                aData['hnd'][i]['gro']=aData['r'].circle(x+ax-aData['cw2'],y+h+ay+aData['cw2'],aData['cw2']);
                aData['hnd'][i]['gro'].attr({'fill': color, 'stroke': color,'stroke-width':1,cursor: "move",'fill-opacity': 1,'opacity':1});
            }else{
                aData['hnd'][i]['gro']=aData['r'].image(aData['rbr'],  x+w+ax, y+h+ay, aData['cw'],aData['cw']);
            }
            aData['hnd'][i]['gro'].node.setAttribute('id','gro_'+i);
        }


        /* close */
        if( aData['dat'][i]['clo'] ) {
            if( aData['cbc']==null || aData['cbc']=='' ) {
                aData['hnd'][i]['gcl']=aData['r'].rect(x+w,y-aData['cw'],aData['cw'],aData['cw'],0);
                aData['hnd'][i]['gcl'].attr({'fill': "#900000", 'stroke':  "#900000",'stroke-width': 1,cursor: "pointer",'fill-opacity': 1,'opacity':1});
            }else{
                aData['hnd'][i]['gcl']=aData['r'].image(aData['cbc'],  x+w, y-aData['cw'],aData['cw'], aData['cw']);
            }       
            aData['hnd'][i]['gcl'].node.setAttribute('id','gcl_'+i);


            /* bind drag for target and gizmo */
            var st1=aData['r'].set();
            st1.push(aData['hnd'][i]['obj']);
        }

        if( aData['mask']!=null )
			aData['hnd'][i]['obj'].insertBefore( aData['mask'] );
		aData['hnd'][i]['g'].toFront();
        if( aData['dat'][i]['clo'] ) 
            aData['hnd'][i]['gcl'].toFront();
        if( aData['dat'][i]['res'] )
           aData['hnd'][i]['grs'].toFront();
        if( aData['dat'][i]['rot'] )
           aData['hnd'][i]['gro'].toFront();
		
		posGizmo( i, cx,cy,1,alpha );
		
        /* DELETE */
        if( aData['dat'][i]['clo'] ) {
            aData['hnd'][i]['gcl'].click(function (event) {
                var id=this.node.getAttribute('id');
                id=bsStrCropAfter(id,'_');
                aData['hnd'][id]['obj'].remove();
                aData['hnd'][id]['g'].remove();
                if( aData['dat'][i]['res'] ) {
                    aData['hnd'][id]['grs'].remove();
                }
                if( aData['dat'][i]['rot'] ) {
                    aData['hnd'][id]['gro'].remove();
                }
                aData['hnd'][id]['gcl'].remove();
                delete(aData['dat'][id]);
                aData['obj_cnt']++;

            });
        }

        /* DRAG */
        aData['hnd'][i]['g'].drag(
            function (dx,dy) {            
                var id=this.node.getAttribute('id');
                id=bsStrCropAfter(id,'_');
				
				this.cx1=this.cx+dx; this.cy1=this.cy+dy;
                posGizmo( id, this.cx1,this.cy1, this.scale, this.alpha );
				
                aData['r'].safari();
            },
            function () {
                var id=this.node.getAttribute('id');
                id=bsStrCropAfter(id,'_');

                this.cx 	= aData['dat'][id]['cx'];
				this.cy 	= aData['dat'][id]['cy'];
				this.scale 	= aData['dat'][id]['scale'];
				this.alpha 	= aData['dat'][id]['alpha'];
            },
            function () {
                var id=this.node.getAttribute('id');
                id=bsStrCropAfter(id,'_');

                aData['dat'][id]['cx']		= this.cx1;
				aData['dat'][id]['cy']		= this.cy1;
            }
        );

       

        /* RESIZE */
        if( aData['dat'][i]['res'] ) {
            aData['hnd'][i]['grs'].drag(
				function (dx,dy) { with(Math){            
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');
					
					w0 = aData['dat'][i]['w'];	h0 = aData['dat'][i]['h'];
					diag2 = sqrt(w0*w0+h0*h0)/2;
					x  = this.ox+dx-this.cx;	y  = this.oy+dy-this.cy;
					r = sqrt(x*x+y*y);
					
					maxsz = aData['dat'][i]['maxsz'];
					if( maxsz>0 && r>maxsz ) r = maxsz;
					
					this.scale1 = r/diag2;
					posGizmo( id, this.cx,this.cy, this.scale1, this.alpha );
					
					aData['r'].safari();
				}},
				function () {
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');

					cw2 = aData['cw2'];
					this.ox 	= aData['hnd'][id]['grs'].attr("x")+cw2;
					this.oy 	= aData['hnd'][id]['grs'].attr("y")+cw2;
					this.cx 	= aData['dat'][id]['cx'];
					this.cy 	= aData['dat'][id]['cy'];
					this.scale 	= aData['dat'][id]['scale'];
					this.alpha 	= aData['dat'][id]['alpha'];
				},
				function () {
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');

					aData['dat'][id]['scale']	= this.scale1;
				}
			);
		}

        /* ROTATE */
		if( aData['dat'][i]['rot'] ) {
            aData['hnd'][i]['gro'].drag(
				function (dx,dy) { with(Math){
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');
					
					x0  = this.ox-this.cx;			y0  = this.oy-this.cy;
					x   = this.ox-this.cx+dx;		y   = this.oy-this.cy+dy;
					aa	= x0*x + y0*y;
					ar	= sqrt( (x0*x0+y0*y0)*(x*x+y*y) );
					
					sign = 0;
					if( x0 != 0 )
						sign = (x*y0/x0 > y) ? -1 : 1;
					else
						sign = (x < x0) ? -1 : 1;
					if( this.ox < this.cx ) sign = -sign;
					
					this.alpha1 = this.alpha + sign*acos(aa/ar)/PI*180;
					posGizmo( id, this.cx,this.cy, this.scale, this.alpha1 );
					
					aData['r'].safari();
				}},
				function () {
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');

					cw2 = aData['cw2'];
					this.ox 	= aData['hnd'][id]['gro'].attr("cx");
					this.oy 	= aData['hnd'][id]['gro'].attr("cy");
					this.cx 	= aData['dat'][id]['cx'];
					this.cy 	= aData['dat'][id]['cy'];
					this.scale 	= aData['dat'][id]['scale'];
					this.alpha 	= aData['dat'][id]['alpha'];
				},
				function () {
					var id=this.node.getAttribute('id');
					id=bsStrCropAfter(id,'_');

					aData['dat'][id]['alpha']	= this.alpha1;
				}
			);
		}
    }

    /** 
     * addObject
     *
     * добавляет raphael-объект в стек
     *
     * @access public
     * @return void
     *
    this.addObject=addObject;
    function addObject(i,type,j,x,y,fs){
        
        aData['obj_cnt']++;
      
        aData['dat'][i]={};
        aData['dat'][i]['obj']=j;     
        aData['dat'][i]['type']=type;
        aData['hnd'][i]['obj'].attr({cursor: "move" });  
        aData['hnd'][i]['obj'].node.setAttribute('id','obj_'+i);


        if (x != null){
           aData['hnd'][i]['obj'].attr({'x':x});
        }
        if (y != null){
           aData['hnd'][i]['obj'].attr({'y':y});
        }

        aData['hnd'][i]['obj']['x']=aData['hnd'][i]['obj'].attr('x');
        aData['hnd'][i]['obj']['y']=aData['hnd'][i]['obj'].attr('y');
        x = aData['hnd'][i]['obj']['x'];
        y = aData['hnd'][i]['obj']['y'];
        aData['dat'][i]['w']= aData['hnd'][i]['obj'].getBBox().width;
        aData['dat'][i]['h']= aData['hnd'][i]['obj'].getBBox().height;
    } */

    this.canvas=canvas;
    var canvas={};    

    /* no # symbol in sel! */
    this.setCanvas=setCanvas;
    function setCanvas(sel,uri,bg,dpi,uri2){
        if( sel!=null ) {
            canvas['container_id']=sel;
            canvas['width'] =$('#'+sel).css('width');
            canvas['height']=$('#'+sel).css('height');
        }else{
            return false;
        }

        if( uri!=null ) {
            canvas['uri']=uri;
        }else{
            canvas['uri']='';
        }
        if( uri2!=null ) {
            canvas['uri2']=uri2;
        }else{
			canvas['uri2']='';
            /*canvas['uri2']='/php/pillow_trn_red.png';*/
        }
        if( bg!=null ) {
            canvas['bg']=bg;
        }else{
            canvas['bg']="";
        }
        if( dpi!=null ) {
            canvas['ar']=dpi;
        }else{
            canvas['ar']=1;
        }
    }

    this.print=print;
    var print={};

    this.setPrint=setPrint;
    function setPrint(sel,x,y,uri,bg,dpi){
        if( sel!=null ) {
            print['container_id']=sel;
            print['width'] =$('#'+sel).css('width');
            print['height']=$('#'+sel).css('height');
        }else{
            return false;
        }

        if( uri!=null ) {
            print['uri']=uri;
        }else{
            print['uri']='';
        }
        if( bg!=null ) {
            print['bg']=bg;
        }else{
            print['bg']="";
        }
        
        if( x!=null ) {
            print['x']=x;
        }else{
            print['x']=$('#'+sel).css('margin-left');
        }
        if( y!=null ) {
            print['y']=y;
        }else{
            print['y']=$('#'+sel).css('margin-top');
        }
        
        if( dpi!=null ) {
            print['ar']=dpi;
        }else{
            print['ar']=1;
        }

		if( canvas['uri2']!=null && canvas['uri2']!="" )
			setUri2(canvas['uri2']);
	}
	
	this.setUri = setUri;
	function setUri(uri) {
		canvas['uri'] = uri;
	}

	this.setUri2 = setUri2;
	function setUri2(uri2) {
		canvas['uri2'] = uri2;
		var o = hRaphael.image( uri2, 0,0, parseInt(print['width']),parseInt(print['height']) );
		if( aData['mask']!=null ) {
			o.insertAfter( aData['mask'] );
			aData['mask'].remove();
		}
		aData['mask'] = o;
	}

    this.getData=getData;
    function getData(){
        var storage={};
        storage['canvas']   = canvas;
        storage['print']    = print;
        storage['objects']  = aData['dat'];
		for( key in storage['objects'] ) {
			storage['objects'][key]['w']  = storage['objects'][key]['w'] *storage['objects'][key]['scale'];
			storage['objects'][key]['h']  = storage['objects'][key]['h'] *storage['objects'][key]['scale'];
			storage['objects'][key]['fs'] = storage['objects'][key]['fs']*storage['objects'][key]['scale'];
			storage['objects'][key]['x']  = storage['objects'][key]['cx'] - storage['objects'][key]['w']/2;
			storage['objects'][key]['y']  = storage['objects'][key]['cy'] - storage['objects'][key]['h']/2;
			storage['objects'][key]['scale'] = 1;
		}
        var t=JSON.stringify(storage);
        delete(storage);
        return t;
    }

    this.setData=setData;
    function setData(t){
/*"objects":{"0.27169487089249156":{"type":"image","fs":null,"ff":null,"text":null,"color":null,"uri":"/usr/people/admin/photos5/34123145/img0179.jpg","w":80,"h":80,"x":10,"y":10,"alpha":0,"visible":true,"res":true,"clo":true,"ax":0,"ay":0},"0.6305817105005551":{"type":"image","fs":null,"ff":null,"text":null,"color":null,"uri":"/usr/people/admin/photos5/34123145/img0183.jpg","w":80,"h":80,"x":10,"y":10,"alpha":0,"visible":true,"res":true,"clo":true,"ax":0,"ay":0}}*/      
        var a=JSON.parse(t);
        for( key in a['objects'] ) {
            if( a['objects'][key]['type']=='image' ) {
                addImage(a['objects'][key]['uri'],a['objects'][key]['x'],a['objects'][key]['y'],a['objects'][key]['w'],a['objects'][key]['h'],a['objects'][key]['alpha']);
            }else if(a['objects'][key]['type']=='text'){
                addText(a['objects'][key]['text'],a['objects'][key]['x'],a['objects'][key]['y'],a['objects'][key]['ff'],a['objects'][key]['fs'],a['objects'][key]['color'],a['objects'][key]['alpha']);
            }
        }
       
        return true;
    }

    this.resetData=resetData;
    function resetData(){
        
        for( key in aData['dat'] ) {
            var o=aData['hnd'][key]['obj'];  
               o.remove(); 
            if( aData['dat'][key]['clo'] ) {
                var o=aData['hnd'][key]['gcl'];  
                    o.remove(); 
            }
            if( aData['dat'][key]['res'] ) {
                var o=aData['hnd'][key]['grs'];  
                    o.remove(); 
            }
            var o=aData['hnd'][key]['g'];  
                o.remove(); 
        }
        delete(aData['dat']);
        aData['dat']={};
        delete(aData['hnd']);
        aData['hnd']={};
       
        return true;
    }




}



