public class CollageBoard extends JComponent implements DropTargetListener, MouseMotionListener,MouseInputListener  {
	
	//se crea el objeto slider
	private JSlider slider;
	
	// lista de imagenes 
    private List<CollagePart> parts = new LinkedList<CollagePart>();//LinkedList E - el tipo de elementos que tuvo
    
    //lugar en esta coleccin
    private RenderingHints hints; //RenderinHints realizan representacin y manipulacin de imgenes servicios.
    
    private float clearRatio = -1;
    
    public CollageBoard() {// constructor 
    	//se asigna el slider con un parameto de 1 a 100 de 50
    	slider = new JSlider(JSlider.HORIZONTAL, 1, 100, 50);
    	//se agregan los numeritos abajo
    	slider.setPaintLabels(true);
    	//saltos del slider 1 + 49 = "50" + 49 = "99"
    	slider.setMajorTickSpacing(49);
    	//se agrea el titulito
    	slider.setBorder(new TitledBorder("Escala en %"));
    	slider.setBackground(new Color(189,236,182));
    	//se crea la clase de syncronisacion
    	MyChangeListener lst = new MyChangeListener();
    	//se asigna la clase de asignacion a el slider
    	slider.addChangeListener(lst);
        createRenderingHints();// Mandar llamar el metodo
        setDropTarget(new DropTarget(this, this));
        addMouseMotionListener(this);
        //se agrega la accion MouseListener
        addMouseListener(this);
        
        
    }
        
    private void createRenderingHints() {
      
    	
        hints = new RenderingHints(RenderingHints.KEY_INTERPOLATION,
                                   RenderingHints.VALUE_INTERPOLATION_BICUBIC);
        hints.put(RenderingHints.KEY_ANTIALIASING,
                  RenderingHints.VALUE_ANTIALIAS_ON);
        hints.put(RenderingHints.KEY_ALPHA_INTERPOLATION,
                  RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        hints.put(RenderingHints.KEY_COLOR_RENDERING,
                  RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        hints.put(RenderingHints.KEY_RENDERING,
                  RenderingHints.VALUE_RENDER_QUALITY);
        
    }
    
    
    // Agrega una imagen a la area de componentes 
    public void addImage(BufferedImage image, int x, int y) {
    	//modificar constructor de clase collagePart para agregar el id
    	// parts.size();
        parts.add(new CollagePart(image, x, y));
       
    }
   
 //-----------------------------------------------ANIMACION DE LIMPIAR AREA------------------------------------------------------   
  
    // limpia el area de trabajo
    public void clear() {
        parts.clear();
        Timer clearTimer = new Timer(1000 / 60, new ClearAnimation());
        clearTimer.start();
    }
    //se crea la animacion 
    private class ClearAnimation implements ActionListener {
        private long DELAY_ANIMATION = 400;
        private long start;
        private boolean isInitialized;

        private ClearAnimation() {
            isInitialized = false;
        }

        public void actionPerformed(ActionEvent e) {
            if (!isInitialized) {
                start = System.currentTimeMillis();
                isInitialized = true;
            }
            
            long elapsed = System.currentTimeMillis() - start;
            if (elapsed > DELAY_ANIMATION) {
                ((Timer) e.getSource()).stop();
                clearRatio = -1;
                parts.clear();
            } else {
                float time = (float) elapsed / (float) DELAY_ANIMATION;
                clearRatio = time;
            }
            
            repaint();
        }
    }
    
 //------------------------------------------------------------------------------------------------------------------------------
    // Pintar componente 
    @Override
    protected void paintComponent(Graphics g) {
        if (isVisible()) {
            Insets insets = getInsets();
            
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHints(hints);

//            
            
            g2.setColor(getBackground());
            g2.fillRect(insets.left, insets.top,
                        getWidth() - insets.left - insets.right, getHeight() - insets.top - insets.bottom);
            
            for (CollagePart part: parts) {
                drawPart(g2, part);
                
            }
        }
    }
     // Agregar los componentes con el mouse 
     // llamar al componente 
    private void drawPart(Graphics2D g2, CollagePart part) {
        if (part.getImage() != null) {

            // como se coloca la imagen 
            int x = part.getX() - part.getImage().getWidth() / 2;
            int y = part.getY() - part.getImage().getHeight() / 2;
            // trasladar a el punto x y y 
            g2.translate(x, y);
            

            Composite composite = g2.getComposite();
            if (clearRatio != -1) {
                g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1.0f - clearRatio));
            }
            
            // agregarlas a el area 
            g2.drawImage(part.getImage(), null, 0, 0);
            
            g2.setComposite(composite);
           
            g2.scale(1, 1);
           
            g2.translate(-x, -y);
        }
    }

    public class CollagePart{
    	
        private BufferedImage image;
        //crear una variable id
        private int x;
        
        private int y;
        
        //private double rotation;
        // cordenadas a donde llega la imagen 
        public CollagePart(BufferedImage image, int x, int y) {
            this.image = image;
            
       //     System.out.println(image +"llego imagen "); 
            
            
            this.x = x;
            //System.out.println(x +"llego al punto x");
            
            this.y = y;
                       
            //System.out.println(y +"llego al punto y ");
        //    this.rotation = rotation;
        }


 // creacion de geters 
		public BufferedImage getImage() {
            return image;
        }

        public int getX() {
        	
           // System.out.println(x);
            return x;
        }

        public int getY() {
        	//System.out.println(y);
            return y;
            
        }

    }

    public void dragEnter(DropTargetDragEvent dtde) {
    	
    }

    public void dragOver(DropTargetDragEvent dtde) {
    }

    public void dropActionChanged(DropTargetDragEvent dtde) {
    }

    public void dragExit(DropTargetEvent dte) {
    }
//-------------------------------SOLTAR------------------------------------------------------------
    public void drop(DropTargetDropEvent dtde) {
        DataFlavor[] flavors = dtde.getCurrentDataFlavors();
        if (flavors == null) {
            return;
        }
        
        for (int i = flavors.length - 1; i >= 0; i--) {
            if (flavors[i].equals(CollageItemTransferHandler.COLLAGE_ITEM_FLAVOR)) {
                dtde.acceptDrop(DnDConstants.ACTION_COPY);  // copy image dentro del area 
                Transferable transferable = dtde.getTransferable();

                CollageItem newImage = null; 
                try {
                    newImage = (CollageItem) transferable.getTransferData(CollageItemTransferHandler.COLLAGE_ITEM_FLAVOR);
                } catch (Exception e) {
                	
                }
                
                if (newImage == null) {
                    return;
                }
                
                GhostGlassPane glassPane = (GhostGlassPane) SwingUtilities.getRootPane(this).getGlassPane();
                Point p = dtde.getLocation();
                

                double phi = Math.PI / 6.0;
                double d = 1.0 - Math.random() * 2.0;
                double rotation = d * phi / 2.0;
                
                addImage(newImage.getThumb(), p.x, p.y);
                
                
                
                
                // XXX: to change when animated
                //a cambiar cuando animada
                glassPane.setImage(null);
                glassPane.setVisible(false);
                DragAndDropLock.setLocked(false);
                
                dtde.dropComplete(true);
                break;
            }
        }
    }
    
//------------------------------------------------------- ARRASTRAR EN AREA DE TRABAJO------------------------------------------------- 
    
    private static final long servialVersionUID = -427212128171436938L;
    
    //metodo del MouseMotionListerner
    
    int xe ;
    int ye ;
    
    CollagePart imagen = null;   
    
    private boolean arrastrando = false;
    
    
	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub
		slider.setVisible(false);
		if(!arrastrando){
			
			imagen = estaDentro(e);
			if(imagen != null){
				
				
				xe=imagen.getX();
				ye=imagen.getY();
				
				arrastrando = true;
			}
		}
		else{
			
			xe = e.getX();
			ye = e.getY();
			CollagePart newCollagePart = imagen;
			newCollagePart.x = xe;
			newCollagePart.y = ye;
			guardar(imagen, newCollagePart);
			repaint();
		}
	}
		
	
	
	private CollagePart guardar(CollagePart oldCollagPart,CollagePart newCollagePart){
		int i = 0;
		for(CollagePart partes: parts){
			
			if (partes.getImage() != null) {

	            int x = partes.getX() - partes.getImage().getWidth() / 2;
	            int x2 = partes.getX() + partes.getImage().getWidth() /2;
	            int y = partes.getY() - partes.getImage().getHeight() / 2;
	            int y2= partes.getY() + partes.getImage().getHeight() /2;
	            
	            if((oldCollagPart.getX()>=x)&&(oldCollagPart.getX()<=x2) && (oldCollagPart.getY()>=y)&&(oldCollagPart.getY()<=y2)&& oldCollagPart.getImage().equals(newCollagePart.getImage())){
	            	parts.remove(i);
	            	parts.add(new CollagePart(oldCollagPart.getImage(), newCollagePart.getX(), newCollagePart.getY()));
	            	return null;
	            }
	            i++;
			}
		}
		
		return null;
	}
	 
	private CollagePart estaDentro(MouseEvent e){
		for(CollagePart partes: parts){
			
			if (partes.getImage() != null) {

	            int x = partes.getX() - partes.getImage().getWidth() / 2;
	            int x2 = partes.getX() + partes.getImage().getWidth() /2;
	            int y = partes.getY() - partes.getImage().getHeight() / 2;
	            int y2= partes.getY() + partes.getImage().getHeight() /2;
	           
	        
	             if(
	            		 (e.getX()>=x)&&(e.getX()<=x2)
	            		 && (e.getY()>=y)&&(e.getY()<=y2)

	            		 ){
	            	 
	            	 return partes;
	             }			
			}
		}
		return null;
	}
	
	@Override
	public void mouseMoved(MouseEvent e) {
		// TODO Auto-generated method stub
		arrastrando = false;
	}
	
	
	//cuando haga click sobre el panel
	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		//verifica que exista alguna imgen donde dio click
		imagen = estaDentro(e);
		if(imagen != null){
			
			//si existe una imgen donde dio click
			xe=imagen.getX() - imagen.getImage().getWidth()/2;
			ye=imagen.getY() - imagen.getImage().getHeight()/2;
			
			//se agrega al slider con un tamao de 200 por 50 en la ubicacion donde esta la imagen
			slider.setBounds(xe, ye, 200,50);
			slider.setVisible(true);
			add(slider);
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	//clase que esta escuchando el cambio de slider
	class MyChangeListener implements ChangeListener {
	    MyChangeListener() {
	    }

	    //metodo de syncronizado con el slider... Cada Vez que mueve la barrita se va activando este.
	    public synchronized void stateChanged(ChangeEvent e) {
	    	
	      
	      //aqui estamos creando un objeto CollagePart para cambiar el tamao de la imagen
	      CollagePart newCollagePart = imagen;

	      //cambiar dimeciones de la imagen.... * falta agrregar la programacion
	      
	      //se guarda la nueva imagen con la nueva dimencion.
	      guardar(imagen, newCollagePart);
	      repaint();
	      
	    }

		
	  }
}    
   