package org.duyi.svq.vast2014;

import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.text.SimpleDateFormat;
import java.util.Date;

import prefuse.Constants;
import prefuse.render.AbstractShapeRenderer;
import prefuse.util.ColorLib;
import prefuse.util.GraphicsLib;
import prefuse.visual.VisualItem;

/**
 * 能够处理时间数据的X轴
 * @author	duyi
 * @date	2014年6月27日
 */
public class XAxisRenderer extends AbstractShapeRenderer {



    private Line2D      m_line = new Line2D.Double();
    private Rectangle2D m_box  = new Rectangle2D.Double();
    
    private int m_xalign;
    private int m_yalign;
    private int m_ascent;
    
    private SimpleDateFormat df = new SimpleDateFormat("yyyy-MM");
    
    /**
     * Create a new AxisRenderer. By default, axis labels are drawn along the
     * left edge and underneath the tick marks.
     */
    public XAxisRenderer() {
        this(Constants.LEFT, Constants.BOTTOM);
    }
    
    /**
     * Create a new AxisRenderer.
     * @param xalign the horizontal alignment for the axis label. One of
     * {@link prefuse.Constants#LEFT}, {@link prefuse.Constants#RIGHT},
     * or {@link prefuse.Constants#CENTER}.
     * @param yalign the vertical alignment for the axis label. One of
     * {@link prefuse.Constants#TOP}, {@link prefuse.Constants#BOTTOM},
     * or {@link prefuse.Constants#CENTER}.
     */
    public XAxisRenderer(int xalign, int yalign) {
        m_xalign = xalign;
        m_yalign = yalign;
    }
    
    /**
     * Set the horizontal alignment of axis labels.
     * @param xalign the horizontal alignment for the axis label. One of
     * {@link prefuse.Constants#LEFT}, {@link prefuse.Constants#RIGHT},
     * or {@link prefuse.Constants#CENTER}.
     */
    public void setHorizontalAlignment(int xalign) {
        m_xalign = xalign;
    }
    
    /**
     * Set the vertical alignment of axis labels.
     * @param yalign the vertical alignment for the axis label. One of
     * {@link prefuse.Constants#TOP}, {@link prefuse.Constants#BOTTOM},
     * or {@link prefuse.Constants#CENTER}.
     */
    public void setVerticalAlignment(int yalign) {
        m_yalign = yalign;
    }
    
    /**
     * @see prefuse.render.AbstractShapeRenderer#getRawShape(prefuse.visual.VisualItem)
     */
    protected Shape getRawShape(VisualItem item) {
        double x1 = item.getDouble(VisualItem.X);
        double y1 = item.getDouble(VisualItem.Y);
        double x2 = item.getDouble(VisualItem.X2);
        double y2 = item.getDouble(VisualItem.Y2);
        m_line.setLine(x1,y1,x2,y2);
        
        if ( !item.canGetString(VisualItem.LABEL) )
            return m_line;
        
        String label = item.getString(VisualItem.LABEL);
        if ( label == null ) return m_line;
        
        FontMetrics fm = DEFAULT_GRAPHICS.getFontMetrics(item.getFont());
        m_ascent = fm.getAscent();
        int h = fm.getHeight();
        int w = fm.stringWidth(label);
        
        double tx, ty;
        
        // get text x-coord
        switch ( m_xalign ) {
        case Constants.FAR_RIGHT:
            tx = x2 + 2;
            break;
        case Constants.FAR_LEFT:
            tx = x1 - w - 2;
            break;
        case Constants.CENTER:
            tx = x1 + (x2-x1)/2 - w/2;
            break;
        case Constants.RIGHT:
            tx = x2 - w;
            break;
        case Constants.LEFT:
        default:
            tx = x1;
        }
        // get text y-coord
        switch ( m_yalign ) {
        case Constants.FAR_TOP:
            ty = y1-h;
            break;
        case Constants.FAR_BOTTOM:
            ty = y2;
            break;
        case Constants.CENTER:
            ty = y1 + (y2-y1)/2 - h/2;
            break;
        case Constants.TOP:
            ty = y1;
            break;
        case Constants.BOTTOM:
        default:
            ty = y2-h; 
        }
        m_box.setFrame(tx,ty,w,h);
        return m_box;
    }
    
    /**
     * @see prefuse.render.Renderer#render(java.awt.Graphics2D, prefuse.visual.VisualItem)
     */
    public void render(Graphics2D g, VisualItem item) { 
    	Shape s = getShape(item); 
    	item.setTextColor(ColorLib.color(Color.black));
    	
    	GraphicsLib.paint(g, item, m_line, getStroke(item), getRenderType(item)); 
    	
    	// check if we have a text label, if so, render it 
    	if ( item.canGetString(VisualItem.LABEL) ) { 
	    	float x = (float)m_box.getMinX(); 
	    	float y = (float)m_box.getMinY() + m_ascent; 
	    	 
	    	// draw label background 
	    	GraphicsLib.paint(g, item, s, null, RENDER_TYPE_FILL); 
	    	 
	    	String ss = item.getString(VisualItem.LABEL); 
	    	ss = ss.replaceAll(",","");
	    	String str = df.format(new Date(Long.parseLong(ss)));
//	    	System.out.println(str);
	    	AffineTransform origTransform = g.getTransform();
	    	AffineTransform transform = this.getTransform(item);
	    	if ( transform != null ) g.setTransform(transform);
	    		
	    	g.setFont(item.getFont()); 
	    	g.setColor(ColorLib.getColor(item.getTextColor())); 
	    	g.drawString(str, x, y);
	    		
	    	if ( transform != null ) g.setTransform(origTransform); 
    	}
	}

    /**
     * @see prefuse.render.Renderer#locatePoint(java.awt.geom.Point2D, prefuse.visual.VisualItem)
     */
    public boolean locatePoint(Point2D p, VisualItem item) {
        Shape s = getShape(item);
        if ( s == null ) {
            return false;
        } else if ( s == m_box && m_box.contains(p) ) {
            return true;
        } else {
            double width = Math.max(2, item.getSize());
            double halfWidth = width/2.0;
            return s.intersects(p.getX()-halfWidth,
                                p.getY()-halfWidth,
                                width,width);
        }
    }

    /**
     * @see prefuse.render.Renderer#setBounds(prefuse.visual.VisualItem)
     */
    public void setBounds(VisualItem item) {
        if ( !m_manageBounds ) return;
        Shape shape = getShape(item);
        if ( shape == null ) {
            item.setBounds(item.getX(), item.getY(), 0, 0);
        } else if ( shape == m_line ) {
            GraphicsLib.setBounds(item, shape, getStroke(item));
        } else {
            m_box.add(m_line.getX1(),m_line.getY1());
            m_box.add(m_line.getX2(),m_line.getY2());
            item.setBounds(m_box.getMinX(), m_box.getMinY(),
                           m_box.getWidth(), m_box.getHeight());
        }
    }
}
