/*******************************************************************************
* Copyright (c)                                                                *
*           2005   Tristan Allwood,                                            *
*           2005   Daniel Burke,                                               *
*           2005   Marc Hull,                                                  *
*           2005   Ekaterina Itskova,                                          *
*           2005   Steve Zymler                                                *
*                                                                              *
* Permission is hereby granted, free of charge, to any person obtaining a      *
* copy of this software and associated documentation files (the                *
* "Software"), to deal in the Software without restriction, including          *
* without limitation the rights to use, copy, modify, merge, publish,          *
* distribute, sublicense, and/or sell copies of the Software, and to           *
* permit persons to whom the Software is furnished to do so, subject to        *
* the following conditions:                                                    *
*                                                                              *
* The above copyright notice and this permission notice shall be included      *
* in all copies or substantial portions of the Software.                       *
*                                                                              *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS      *
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF                   *
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.       *
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY         *
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,         *
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE            *
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                       *
*******************************************************************************/
/*
 * Created on 21-Oct-2004
 */
package uk.ac.ic.doc.kevlar.gui.internal.caches;

import java.io.FileNotFoundException;

import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;

import uk.ac.ic.doc.kevlar.Kevlar;


/**
 * @author Marc
 **/
public class Utils {

    public static final int ALIGN_LEFT = 0;
    public static final int ALIGN_RIGHT = 1;
    public static final int ALIGN_CENTER = 2;
    
    public static final int LEFT_MOUSE_BUTTON = 1;
    public static final int MIDDLE_MOUSE_BUTTON = 2;
    public static final int RIGHT_MOUSE_BUTTON = 2;
    
    public static String LEFT = "_left.png";
    public static String RIGHT = "_right.png";
    public static String MIDDLE = "_middle.png";
    
    public static String NORMAL = "_normal.png";
    public static String ROLLOVER = "_rollover.png";
    public static String SELECTED = "_selected.png";
    
	public static void drawHorizontalBar(GC gc, String skin, Rectangle area, boolean drawLeft, boolean drawRight) {
		
	    try {
	    
	        Rectangle bounds;

	        
	        Image left = null;
	        Rectangle leftRect = null;
	        if(drawLeft)
	        {
		        left = ImageCache.get(skin+"_left.png");
		        bounds = left.getBounds();
		        leftRect = new Rectangle(area.x, area.y, bounds.width, area.height);
	        }
	        
	        Image right = null;
	        Rectangle rightRect = null;
	        if(drawRight)
	        {
		        right = ImageCache.get(skin+"_right.png");
		        bounds = right.getBounds();
		        rightRect = new Rectangle(area.x+area.width-bounds.width, area.y, bounds.width, area.height);
	        }
	        
	        int sideWidths = (drawLeft ? leftRect.width : 0) + (drawRight ? rightRect.width : 0);
	        
	        if (area.width - sideWidths > 0) {
		
	            Image middle = ImageCache.get(skin+"_middle.png");
	            bounds = middle.getBounds();
	            Rectangle middleRect = new Rectangle(
	                    (drawLeft ? leftRect.x : area.x) + (drawLeft ? leftRect.width : 0),
	                    area.y, 
	                    area.width - (drawRight ? rightRect.width : 0) - (drawLeft ? leftRect.width : 0), 
	                    area.height);
		
	            drawImage(gc, middle, middleRect);
	            
	            if(drawLeft)
	            {
	                drawImage(gc, left, leftRect);
	            }
	           
	            if(drawRight)
	            {
	                drawImage(gc, right, rightRect);
	            }
			
	        } else {
			
	            Image bar = ImageCache.get(skin+"_small.png");
	            drawImage(gc, bar, area);
			
	        }
	        
	    } catch (FileNotFoundException e) {
	        if(Kevlar.DEBUG)
	        {
	            e.printStackTrace();
	        }
	    }
		
	}
	
	public static void drawHorizontalBar(GC gc, String skin, Rectangle area) {
		drawHorizontalBar(gc, skin, area, true, true);
	    
	    /*
	    try {
	    
	        Rectangle bounds;

	        Image left = ImageCache.get(skin+"_left.png");
	        bounds = left.getBounds();
	        Rectangle leftRect = new Rectangle(area.x, area.y, bounds.width, area.height);
		
	        Image right = ImageCache.get(skin+"_right.png");
	        bounds = right.getBounds();
	        Rectangle rightRect = new Rectangle(area.x+area.width-bounds.width, area.y, bounds.width, area.height);
		
	        if (area.width-rightRect.width-leftRect.width > 0) {
		
	            Image middle = ImageCache.get(skin+"_middle.png");
	            bounds = middle.getBounds();
	            Rectangle middleRect = new Rectangle(leftRect.x+leftRect.width, area.y, area.width-rightRect.width-leftRect.width, area.height);
		
	            drawImage(gc, middle, middleRect);
	            drawImage(gc, left, leftRect);
	            drawImage(gc, right, rightRect); 
			
	        } else {
			
	            Image bar = ImageCache.get(skin+"_small.png");
	            drawImage(gc, bar, area);
			
	        }
	        
	    } catch (FileNotFoundException e) {
	       
	        // TODO Something when a horizontal bar can't be drawn because the image files cannot be found
	        
	    }
		*/
	}

	public static void drawVerticalBar(GC gc, String skin, Rectangle area)
	{
	    drawVerticalBar(gc, skin, area, true, true); 
	}
	
	public static void drawVerticalBar(GC gc, String skin, Rectangle area, boolean drawTop, boolean drawBottom) {
		
	    try {
	        
	        Rectangle bounds;
	        
	        Image top = null; 
	        Rectangle topRect = null;
	        
	        if(drawTop)
	        {
		        top = ImageCache.get(skin+"_top.png");
		        bounds = top.getBounds();
		        topRect = new Rectangle(area.x, area.y, area.width, bounds.height);
	        }
	        
	        Image bottom = null;
	        Rectangle bottomRect = null;
	        
	        if(drawBottom)
	        {
		        bottom = ImageCache.get(skin+"_bottom.png");
		        bounds = bottom.getBounds();
		        bottomRect = new Rectangle(area.x, area.y+area.height-bounds.height, area.width, bounds.height);
	        }
	        
	        int edgeWidths = (drawTop ? topRect.height : 0) + (drawBottom ? bottomRect.height : 0);
	        
	        if (area.height - edgeWidths > 0) {
	            
	            Image middle = ImageCache.get(skin+"_middle.png");
	            bounds = middle.getBounds();
	            Rectangle middleRect = 
	                new Rectangle(
	                        area.x,
	                        (drawTop ? topRect.y : area.y) + (drawTop ? topRect.height : 0),
	                        area.width, 
	                        area.height-(drawTop ? topRect.height : 0) - (drawBottom ? bottomRect.height : 0));
	            
	            drawImage(gc, middle, middleRect);
	            if(drawTop)
	            {
	                drawImage(gc, top, topRect);
	            }
	            if(drawBottom)
	            {
	                drawImage(gc, bottom, bottomRect);
	            }
	            
	        } else {
	            
	            Image bar = ImageCache.get(skin+"_small.png");
	            drawImage(gc, bar, area);
	            
	        }
	        
	    } catch (FileNotFoundException e) {
	        
	        // TODO Something when a vertical bar can't be drawn because the image files cannot be found
	        
	    }
		
	}

	public static void drawBox(GC gc, Rectangle rect, String skin) {
		
	    try {
	    
	        Rectangle bounds;
	        
	        Image topLeft = ImageCache.get(skin+"_top_left.png");
	        bounds = topLeft.getBounds();
	        Rectangle topLeftRect = new Rectangle(rect.x, rect.y, bounds.width, bounds.height);
	        
	        Image topRight = ImageCache.get(skin+"_top_right.png");
	        bounds = topRight.getBounds();
	        Rectangle topRightRect = new Rectangle(rect.x+rect.width-bounds.width, rect.y, bounds.width, bounds.height);
	        
	        Image bottomLeft = ImageCache.get(skin+"_bottom_left.png");
	        bounds = bottomLeft.getBounds();
	        Rectangle bottomLeftRect = new Rectangle(rect.x, rect.y+rect.height-bounds.height, bounds.width, bounds.height);
	        
	        Image bottomRight = ImageCache.get(skin+"_bottom_right.png");
	        bounds = bottomRight.getBounds();
	        Rectangle bottomRightRect = new Rectangle(rect.x+rect.width-bounds.width, rect.y+rect.height-bounds.height, bounds.width, bounds.height);
	        
	        
	        Image topMiddle = ImageCache.get(skin+"_top_middle.png");
	        bounds = topMiddle.getBounds();
	        Rectangle topMiddleRect = new Rectangle(topLeftRect.x+topLeftRect.width, rect.y, rect.width-topRightRect.width-topLeftRect.width, bounds.height);
	        
	        Image bottomMiddle = ImageCache.get(skin+"_bottom_middle.png");
	        bounds = bottomMiddle.getBounds();
	        Rectangle bottomMiddleRect = new Rectangle(bottomLeftRect.x+bottomLeftRect.width, rect.y+rect.height-bounds.height, rect.width-bottomRightRect.width-bottomLeftRect.width, bounds.height);
	        
	        Image middleLeft = ImageCache.get(skin+"_middle_left.png");
	        bounds = middleLeft.getBounds();
	        Rectangle middleLeftRect = new Rectangle(rect.x, topLeftRect.y+topLeftRect.height, bounds.width, rect.height-bottomLeftRect.height-topLeftRect.height);
	        
	        Image middleRight = ImageCache.get(skin+"_middle_right.png");
	        bounds = middleRight.getBounds();
	        Rectangle middleRightRect = new Rectangle(rect.x+rect.width-bounds.width, topRightRect.y+topRightRect.height, bounds.width, rect.height-bottomRightRect.height-topRightRect.height);
	        
	        Image middle = ImageCache.get(skin+"_middle_middle.png");
	        bounds = middle.getBounds();
	        Rectangle middleRect = new Rectangle(middleLeftRect.x+middleLeftRect.width, topMiddleRect.y+topMiddleRect.height, rect.width-middleRightRect.width-middleLeftRect.width, rect.height-bottomMiddleRect.height-topMiddleRect.height);
	        
	        drawImage(gc, middle, middleRect);			
	        drawImage(gc, topMiddle, topMiddleRect);
	        drawImage(gc, bottomMiddle, bottomMiddleRect);
	        drawImage(gc, middleLeft, middleLeftRect);
	        drawImage(gc, middleRight, middleRightRect);
	        drawImage(gc, topLeft, topLeftRect);
	        drawImage(gc, topRight, topRightRect);
	        drawImage(gc, bottomLeft, bottomLeftRect);
	        drawImage(gc, bottomRight, bottomRightRect);
	        
	    } catch (FileNotFoundException e) {
	        
	        // TODO Something when a box can't be drawn because the image files cannot be found
	        
	    }
				
	}
		
	public static void drawImage(GC gc, Image image, Rectangle rect) {
		
	    if (rect.width > 0 && rect.height > 0) {
	    
	        Rectangle bounds = image.getBounds();
	        gc.drawImage(image, 0, 0, bounds.width, bounds.height, rect.x, rect.y, rect.width, rect.height);
	        
	    }
		
	}
	
	
	public static void drawImage(GC gc, int imageX, int imageY, double imageZoom, Image image, Rectangle redrawArea)
	{	    
        Rectangle bounds = image.getBounds();
        
        int zoomedSrcx = Math.max(0, redrawArea.x - imageX) ;
        int srcx = (int)(zoomedSrcx / imageZoom);
        // The redraw width that is right of the image
        int adjustedRedrawWidth = Math.min(redrawArea.width, redrawArea.x + redrawArea.width - imageX);
        int srcw = Math.min((int)(adjustedRedrawWidth / imageZoom), bounds.width - srcx );	     
        
        int destx = Math.max(redrawArea.x, imageX);
        int destw = Math.min(redrawArea.x + redrawArea.width, imageX + (int)(bounds.width * imageZoom)) - Math.max(redrawArea.x, imageX);
        
        if(srcw <= 0 || destw <= 0)
        {
            return;
        }
        
        int zoomedSrcy = Math.max(0, redrawArea.y - imageY) ;
        int srcy = (int)(zoomedSrcy / imageZoom);
        // The redraw width that is right of the image
        int adjustedRedrawHeight = Math.min(redrawArea.height, redrawArea.y + redrawArea.height - imageY);
        int srch = Math.min((int)(adjustedRedrawHeight / imageZoom), bounds.height - srcy );	     
        
        int desty = Math.max(redrawArea.y, imageY);
        int desth = Math.min(redrawArea.y + redrawArea.height, imageY + (int)(bounds.height * imageZoom)) - Math.max(redrawArea.y, imageY);
        
        if(srch <= 0 || desth <= 0)
        {
            return;
        }
        
        destx -= redrawArea.x;
        desty -= redrawArea.y;
        
        gc.drawImage(image, srcx, srcy, srcw, srch, 
                destx, desty, destw, desth);
	}
	
	public static int drawText(GC gc, String text, Rectangle bounds, int alignment) {
	    
	    int cap = capText(gc, text, bounds.width, "...");
		
		String finalText;
		
		if (cap < text.length()) {
		    
		    finalText = text.substring(0, cap)+"...";
		    
		} else {
		    
		    finalText = text;
		    
		}

		Point textBounds = gc.textExtent(finalText);
		
		if (alignment == ALIGN_LEFT) {
		    
		    gc.drawText(finalText, bounds.x, bounds.y+(bounds.height-textBounds.y)/2, true);
		    
		} else if (alignment == ALIGN_RIGHT) {
		
		    gc.drawText(finalText, bounds.x+bounds.width-textBounds.x, bounds.y+(bounds.height-textBounds.y)/2, true);
		    
		} else if (alignment == ALIGN_CENTER) {
		    
		    gc.drawText(finalText, bounds.x+(bounds.width-textBounds.x)/2, bounds.y+(bounds.height-textBounds.y)/2, true);
		    
		}
		
		return cap;
	    
	}
	
	public static int capText(GC gc, String text, int width, String ext) {

		String temp = text;
		
		if (gc.textExtent(temp).x > width) {
		
			while (temp.length() > 0 && gc.textExtent(temp+ext).x > width) {
			
				temp = temp.substring(0, temp.length()-1);
				
			}
			
//			temp = temp + "...";
			
		}

		return temp.length();
		
	}
	
	public static int distance(Point src, Point dest) {
	    
	    return (int)Math.round(Math.sqrt((src.x-dest.x)*(src.x-dest.x)+(src.y-dest.y)*(src.y-dest.y))); 
	    
	}
	
}
