/*******************************************************************************
 * Copyright (c) 2007 Exadel, Inc. and Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is made available under the terms of the
 * Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Exadel, Inc. and Red Hat, Inc. - initial API and implementation
 ******************************************************************************/ 
package org.jboss.tools.jst.web.tiles.ui.editor.print;

import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.PolylineConnection;
import org.eclipse.draw2d.geometry.PointList;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.LayerConstants;
import org.eclipse.gef.editparts.LayerManager;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;

import org.jboss.tools.jst.web.tiles.ui.editor.figures.DefinitionFigure;

public class PagesView extends Composite implements MouseListener,PaintListener{

   double viewScale = 0.25;
   int pageCount = 0;
   boolean selectionEnabled = false;
   Dimension containerSize;
   Pages pages;
   int pW = 0;
   int pH = 0;
   int zeroX = 100;
   int zeroY = 0;
   GraphicalViewer viewer;
   boolean recount = true;
   List<IFigure> figures = new Vector<IFigure>();
   	
   public PagesView(Pages p, Dimension viewSize,Composite parent, int style) {
   		super (parent, style);
	  if(p.isTextPrint()){
		 this.containerSize = viewSize;
		 this.pages = p;
	  }else{
		 this.containerSize = viewSize;
		 this.pages = p;
		 this.viewer = p.getViewer();
		 this.addMouseListener(this);
		 this.viewScale = calculateScale(containerSize,pages.getDimension());
		 PropertyChangeListener pcl = new PropertyChangeListener(){
			 public void propertyChange(PropertyChangeEvent e){
				  if(e.getPropertyName().equals("scale")){ //$NON-NLS-1$
						setViewScale(calculateScale(containerSize,pages.getDimension()));
						if(pageCount!=pages.getSourcePagesCount()){
							recount = true;	
							pageCount=pages.getSourcePagesCount();
						}else{
							recount = false;
						}
						redraw();
				  }
			 }
		 };
		 pages.addPropertyChangeListener(pcl);
		 this.addPaintListener(this);
		 this.pageCount = pages.getSourcePagesCount();
	  }
 }

   public double calculateScale(Dimension panelSize, Dimension componentSize){
	  double sX = 1;
	  double sY = 1;
	  double s = 1;
	  if(panelSize.width>componentSize.width){
		 sX = (double)1;
	  }else{
		 sX = (double)panelSize.width/componentSize.width;
	  }
	  if(panelSize.height>componentSize.height){
		 sY = (double)1;
	  }else{
		 sY = (double)panelSize.height/componentSize.height;
	  }
	  if(sX<sY){
		 s=sX;
	  }else{
		 s=sY;
	  }
	  return s;
   }

   public void getChilds(IFigure f){
	for(Iterator i = f.getChildren().iterator(); i.hasNext();){
		IFigure o = (IFigure)i.next();
		figures.add(o);
		getChilds(o);
	}
   }
   
   public int getTrueHeight(Label label, double vScale){
	String s = label.getText();
	Font ff = label.getFont();
	FontData fd = ff.getFontData()[0];
	int h = fd.getHeight();
	int nh = (int)(h*vScale);
	if(nh>0){
		fd.setHeight(nh);
		Font f2 = new Font(null,fd);
		int dmm = FigureUtilities.getTextWidth(s, f2);
		int labW = (int)(label.getBounds().width*vScale);
		while(labW>dmm){
			nh++;
			fd.setHeight(nh);
			Font f3 = new Font(null,fd);
			dmm = FigureUtilities.getTextWidth(s, f3);
			f3.dispose();
		}
		
		f2.dispose();
		return nh;
	}
   	return 0;
   }
   
   public void paintControl(PaintEvent pe){
   		
	  GC g2 = pe.gc;
  Color white = new Color(pe.display,0xff,0xff,0xff);
  Color black = new Color(pe.display,0x00,0x00,0x00);
  Color gray = pe.display.getSystemColor(SWT.COLOR_GRAY);
  Color yellowColor = new Color(null, 0xff, 0xf6, 0xcb);
		
	int xmax = 0;
	int ymax = 0;
	int cx = 0;
	int cy = 0;
	for(int i=0; i<pages.getSourcePagesCount(); i++){
		   Rectangle nrz = new Rectangle((int)Math.round(pages.getSourcePage(i).getRectangle().x*viewScale),(int)Math.round(pages.getSourcePage(i).getRectangle().y*viewScale),(int)Math.round(pages.getSourcePage(i).getRectangle().width*viewScale),(int)Math.round(pages.getSourcePage(i).getRectangle().height*viewScale));
		   if((nrz.y+nrz.height)>ymax){
			ymax = nrz.y+nrz.height;
			if(recount)pH = nrz.height;
			cy++;
		   }
		   if((nrz.x+nrz.width)>xmax){
			xmax = nrz.x+nrz.width;
			if(recount)pW = nrz.width;
			cx++;
		   }
	}

	recount = false;
	ymax = cy*pH;
	xmax = cx*pW;  
	
	zeroX = (int)(this.containerSize.width-xmax)/2;
	zeroY = (int)(this.containerSize.height-ymax)/2;
	  	//--->paint viewer!!!!
	LayerManager lm = (LayerManager)viewer.getEditPartRegistry().get(LayerManager.ID);
	IFigure f = lm.getLayer(LayerConstants.PRINTABLE_LAYERS);
	if(figures.isEmpty())getChilds(f);
	
	int ix=0;
	int iy=0;
	for(int i=0; i<figures.size();i++){
			IFigure f1 = (IFigure)figures.get(i);
			if(f1.getBounds().x<0){
				if(f1.getBounds().x<ix)ix=f1.getBounds().x; 
			}
			if(f1.getBounds().y<0){
				if(f1.getBounds().y<iy)iy=f1.getBounds().y; 
			}
	}
	
	for(int i=0; i<figures.size();i++){
		IFigure f1 = (IFigure)figures.get(i);
		Rectangle r = new Rectangle(f1.getBounds().x+Math.abs(ix),f1.getBounds().y+Math.abs(iy),f1.getBounds().width,f1.getBounds().height);
		Rectangle rs = new Rectangle((int)(r.x*viewScale)+zeroX,(int)(r.y*viewScale)+zeroY,(int)(r.width*viewScale),(int)(r.height*viewScale));
				
		if(f1 instanceof PolylineConnection){
			PolylineConnection plc = (PolylineConnection)f1;
			PointList pl = plc.getPoints();	
			for(int j=0; j<pl.size()-1; j++){
				Point p = new Point(pl.getPoint(j).x+Math.abs(ix),pl.getPoint(j).y+Math.abs(iy));
				Point p1 = new Point(pl.getPoint(j+1).x+Math.abs(ix),pl.getPoint(j+1).y+Math.abs(iy));
				g2.setBackground(white);
				g2.setForeground(gray);
				g2.setLineStyle(SWT.LINE_SOLID);
				g2.drawLine((int)(p.x*viewScale)+zeroX,(int)(p.y*viewScale)+zeroY,(int)(p1.x*viewScale)+zeroX,(int)(p1.y*viewScale)+zeroY);	
			}
		}else{
			if(f1 instanceof DefinitionFigure){
				g2.setForeground(black);
				g2.setBackground(yellowColor);
				g2.fillRectangle(rs.x,rs.y,rs.width,rs.height);	
				g2.drawRectangle(rs.x,rs.y,rs.width,rs.height);
			}else{
				if(f1 instanceof Label){
					String s = ((Label)f1).getText();
					Font ff = f1.getFont();
						FigureUtilities.getTextWidth(s, ff);
					FontData fd = ff.getFontData()[0];
					fd.getHeight();
					int nn = this.getTrueHeight((Label)f1,viewScale);
					if(nn>0){
						fd.setHeight(nn);
						Font f2 = new Font(pe.display,fd);
						g2.setFont(f2);
						g2.setBackground(white);
						g2.drawString(s,rs.x,rs.y);
						f2.dispose();
					}
				}
			}
		}
		
	}

	g2.setBackground(black);
	g2.setForeground(black);
	g2.setLineStyle(SWT.LINE_DOT);
	
	g2.drawLine(xmax+zeroX,zeroY,xmax+zeroX,ymax+zeroY);
	g2.drawLine(zeroX,ymax+zeroY,xmax+zeroX,ymax+zeroY);

	int tmp = ymax;

	List<Integer> xx = new ArrayList<Integer>();
	List<Integer> yy = new ArrayList<Integer>();

	while(tmp>0){
		g2.drawLine(zeroX,tmp - pH+zeroY,xmax+zeroX,tmp - pH+zeroY);
		tmp = tmp - pH;
		yy.add(Integer.valueOf(tmp));
	}
	
	tmp = xmax;
	
	while(tmp>0){
		g2.drawLine(tmp - pW+zeroX,zeroY,tmp - pW+zeroX,ymax+zeroY);
		tmp = tmp - pW;
		xx.add(Integer.valueOf(tmp));
	}
	
	List<Rectangle> rec = new ArrayList<Rectangle>();
	
	for(int i=0; i<yy.size();i++){
		for(int j=0; j<xx.size();j++){
			rec.add(new Rectangle(((Integer)xx.get(j)).intValue()+zeroX,((Integer)yy.get(i)).intValue()+zeroY,pW,pH));	
		}
	}
	Object[] rn = rec.toArray();
	 
		 for(int i=0; i<pages.getSourcePagesCount(); i++){
			if(!pages.getSourcePage(i).isSelected()){
				Rectangle sr = pages.getSourcePage(i).getRectangle();
				Point p = new Point((int)Math.round(sr.x*viewScale+pW/2+zeroX),(int)Math.round(sr.y*viewScale+pH/2+zeroY));
				for (int j=0; j<rn.length; j++){
					Rectangle rnt = (Rectangle)rn[j]; 
					if(rnt.contains(p)){
						g2.setXORMode(true);
						g2.setBackground(pe.display.getSystemColor(SWT.COLOR_DARK_GRAY));
						Rectangle nr = new Rectangle(rnt.x,rnt.y,pW+1,pH+1);
						g2.fillRectangle(nr);
						g2.setXORMode(false);						   
					}
				}
			 }
		  }
		  
	g2.dispose();
	pe.gc.dispose();
   }

   public void setViewScale(double viewScale){
	  this.viewScale = viewScale;
   }

   public double getViewScale(){
	  return this.viewScale;
   }

   public Dimension getMinimumSize(){
	  return getPreferredSize();
   }

   public Dimension getMaximumSize(){
	  return getPreferredSize();
   }

   public Dimension getPreferredSize(){
	  return new Dimension((int)(pages.getDimension().width*viewScale),(int)(pages.getDimension().height*viewScale));
   }

   public Point getSize(){
	  return new Point(this.getPreferredSize().width,this.getPreferredSize().height);
   }

   public int getWidth(){
	  return this.getPreferredSize().width;
   }

   public int getHeight(){
	  return this.getPreferredSize().height;
   }

   public Rectangle getBounds(){
	  return new Rectangle(this.getLocation().x,this.getLocation().y,this.getPreferredSize().width,this.getPreferredSize().height);
   }

   public void setSelectionEnabled(boolean value){
	  this.selectionEnabled = value;
   }

   public void mouseDoubleClick(MouseEvent e){
   }
   public void mouseDown(MouseEvent e){
	if(selectionEnabled){
			 Point p = new Point(e.x,e.y);
			 for(int i=0; i<this.pages.getSourcePagesCount(); i++){
				Rectangle nr = new Rectangle((int)(pages.getSourcePage(i).getRectangle().x*viewScale)+zeroX,(int)(pages.getSourcePage(i).getRectangle().y*viewScale)+zeroY,(int)(pages.getSourcePage(i).getRectangle().width*viewScale),(int)(pages.getSourcePage(i).getRectangle().height*viewScale));
				if(nr.contains(p)){
				   pages.getSourcePage(i).setSelected(!pages.getSourcePage(i).isSelected());
				  this.redraw();
				}
			 }
		  }
   }
   public void mouseUp(MouseEvent e){
   }
   
}
