/*  
 *  src/org/metaqtl/graph/MetaGraphPar.java
 * 
 *  $Author: veyrieras $, $Date: 2006-10-17 15:41:55 $, $Version$
 *
 *  MetaQTL : a Java package for QTL Meta-Analysis
 * 
 *  Copyright (C) 2003-2006  Jean-Baptiste Veyrieras, INRA, France.
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA * 
 */
package org.metaqtl.graph;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Stroke;
import java.util.ArrayList;
import java.util.StringTokenizer;


/**
 * 
 */
public final class MetaGraphPar {
	/*
	* General parameters
	*/
	/**
	* The horizontal space between layers.
	*/
	public static double LAYER_HSPACE = 20.0;
	/**
	* The vertical space between layers.
	*/
	public static double LAYER_VSPACE = 20.0;
	/**
	 * The default width.
	 */
	public static double DEFAULT_WIDTH       = 600.0; 
	/**
	 * The default height.
	 */
	public static double DEFAULT_HEIGHT      = 400.0;
	/**
	 * The color of the backgroud. Default is white.
	 */
	public static Color BACKGROUND_COLOR	 = Color.WHITE;
	
	/*
	 * Qtl parameters
	 */
	/**
	 * The vertical space between Qtl shapes. Default is 5.0
	 */
	public static double QTL_VSPACE			= 20.0;
	/**
	 * The horizontal space between Qtl shapes. Default is 5.0
	 */
	public static double QTL_HSPACE			= 10.0;
	
	public static double QTL_TREE_SPACE     = 50.0;
	
	public static double TREE_NODE_WIDTH    = 5.0;
	/**
	 * Add the Qtl name. Default is true
	 */
	public static boolean WITH_QTL_NAME		= true;
	/**
	 * The font used for the Qtl names.
	 * Default is Times with type plain and size 8.
	 */
	public static Font QTL_NAME_FONT		 = new Font("Verdana", Font.PLAIN, 10);
	
	public static Font MARKER_NAME_FONT      = new Font("Verdana", Font.PLAIN, 10);
	
	public static Font MARKER_POSITION_FONT  = new Font("Verdana", Font.PLAIN, 10);
	
	public static Font CHROM_NAME_FONT       = new Font("Verdana", Font.BOLD, 12);
	/**
	 * The color of the QTL names. Default is black
	 */
	public static Color QTL_NAME_COLOR		 = Color.BLACK;
	/**
	 * The space magnification between the Qtl name and the Qtl confidence
	 * interval.
	 */
	public static double QTL_NAME_VSPACE_CEX = 1;
	
	public static boolean WITH_MAP_NAME = true;
	
	public static boolean WITH_CHROM_NAME = true;
	
	
	public static double QTL_PCH_SIZE = 5;
	
	public static boolean WITH_LEGEND = true;
	/**
	 * The magnification for the tick of the QTL.
	 */
	public static double QTL_TICK_WIDTH_CEX = 0.1;
	/**
	 * The color palete for the QTL partition.
	 * Default is null.
	 */
	public static Color[] QTL_PALETTE = null;
	/**
	 * 
	 */
	public static Color[] PROBA_PALETTE = null;
	
	public static int     PROBA_BIN    = 20;
	/*
	 * Chromosome parameters
	 */
	/**
	 * The width of the chromosome. Default is 20.0
	 */
	public static double CHROM_WIDTH = 30.0;
	
	public static double QTL_CI_WIDTH = 10.0;
	
	public static double CHROM_NAME_HSPACE = 20.0;
	
	public static boolean WITH_MARKER_NAME 	   = true;
	
	public static int CHROM_ALIGN_MODE         = ChromLayer.ALIGN_FIRST_MARKER;
	
	public static boolean WITH_MARKER_POSITION = true;
	/**
	 * The default cex parameter for flanking regions at the 
	 * top and the end of the chromosome.
	 */
	public static double CHROM_FLANKING_CEX = 0.10;
	/**
	 * The stroke of the chromosome shape.
	 * Default is <code>BasicStroke</code>
	 */
	public static Stroke CHROM_STROKE		     = new BasicStroke();
	
	public static Stroke CHROM_TICK_STROKE		 = new BasicStroke();
	
	public static double MAKER_NAME_VSPACE = 1;
	
	/**
	 * The color of the stroke of the Chromosome shape.
	 * Default is black.
	 */
	public static Color CHROM_STROKE_COLOR   = Color.BLACK;
	/**
	 * The width of the marker ticks.
	 */
	public static double CHROM_TICK_WIDTH_1 	 = 10;
	
	public static double CHROM_TICK_WIDTH_2 	 = 20;
	
	public static double CHROM_TICK_WIDTH_3 	 = 10;
	
	public static double QTL_POS_HEIGHT_CEX      = 0.01;
	
	public static double QTL_POS_WIDTH_CEX       = 1.5;
	/**
	 * The color of the marker ticks on the chromosome.
	 * Default is black. 
	 */
	public static Color CHROM_TICK_COLOR	 = Color.BLACK;
	
	public static double QTL_NAME_SPACE          = 30.0;
	
	public static double CHROM_DISTANCE_SCALE    = 5.0;
	
	public static double QTL_CI_WIDTH_CEX        = 0.25;
	
	public static double QTL_PROB_WIDTH = 20;
	
	public static Font LEGEND_FONT = new Font("Verdana", Font.PLAIN, 10);
	
	public static double LEGEND_PART_HEIGHT = 20;
	
	public static double LEGEND_PART_WIDTH  = 50;
	
	public static double LEGEND_HSPACE   = 5;
	
	public static double LEGEND_BOX_CEX = 0.5;
	
	public static int LEGEND_SCALE_UNIT = 5;
	
	public static boolean WITH_COMMON_MARKER = false;
	
	private static ArrayList QTL_COLOR_LIST;
	
	public static Color PROBA_FROM_COLOR = Color.WHITE;
	
	public static Color PROBA_TO_COLOR = Color.RED;
	
	public static Color SINGLE_COMMON_COLOR = Color.GRAY;
	
	public static Color POS_COMMON_COLOR = Color.BLUE;
	
	public static Color NEG_COMMON_COLOR = Color.RED;
	
	public static double COMMON_STROKE_WIDTH = 5;
	
	public static double LEGEND_GRAD_HEIGHT = 10;
	
	public static double LEGEND_GRAD_WIDTH  = 50;
	
	public static double QTL_TREE_SCALE = 1;
	
	private MetaGraphPar() {}

	/**
	 * @param parameter
	 * @param value
	 */
	public static void set(String parameter, String value) throws IllegalArgumentException {
		if (parameter.equals("LAYER_HSPACE")) {
			LAYER_HSPACE = Double.parseDouble(value);
		}
		if (parameter.equals("LAYER_VSPACE")) {
			LAYER_VSPACE = Double.parseDouble(value);
		}
		if (parameter.equals("BACKGROUND_COLOR")) {
			BACKGROUND_COLOR = string2color(value);
		}	
		if (parameter.equals("QTL_HSPACE")) {
			QTL_HSPACE = Double.parseDouble(value);
		}
		if (parameter.equals("QTL_VSPACE")) {
			QTL_VSPACE = Double.parseDouble(value);
		}
		if (parameter.equals("QTL_TREE_SPACE")) {
			QTL_TREE_SPACE = Double.parseDouble(value);
		}
		if (parameter.equals("QTL_TREE_SCALE")) {
			QTL_TREE_SCALE = Double.parseDouble(value);
		}
		if (parameter.equals("QTL_NAME_WITH")) {
			WITH_QTL_NAME = Boolean.parseBoolean(value);
		}
		if (parameter.equals("QTL_NAME_FONT")) {
			QTL_NAME_FONT = string2font(value);
		}
		if (parameter.equals("MARKER_NAME_FONT")) {
			MARKER_NAME_FONT = string2font(value);
		}
		if (parameter.equals("MARKER_POSITION_FONT")) {
			MARKER_POSITION_FONT = string2font(value);
		}
		if (parameter.equals("CHROM_NAME_FONT")) {
			CHROM_NAME_FONT = string2font(value);
		}
		if (parameter.equals("CHROM_WIDTH")) {
			CHROM_WIDTH = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_FLANKING_CEX")) {
			CHROM_FLANKING_CEX = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_TICK_WIDTH_1")) {
			CHROM_TICK_WIDTH_1 = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_TICK_WIDTH_2")) {
			CHROM_TICK_WIDTH_2 = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_TICK_WIDTH_3")) {
			CHROM_TICK_WIDTH_3 = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_TICK_COLOR")) {
			CHROM_TICK_COLOR = string2color(value);
		}
		if (parameter.equals("CHROM_DISTANCE_SCALE")) {
			CHROM_DISTANCE_SCALE = Double.parseDouble(value);
		}
		if (parameter.equals("COMMON_STROKE_WIDTH")) {
			COMMON_STROKE_WIDTH = Double.parseDouble(value);
		}
		if (parameter.equals("CHROM_ALIGN_MODE")) {
			CHROM_ALIGN_MODE = Integer.parseInt(value);
		}
		if (parameter.startsWith("QTL_COLOR")) {
			if (QTL_COLOR_LIST == null) {
				QTL_COLOR_LIST = new ArrayList();
			}
			QTL_COLOR_LIST.add(string2color(value));
		}
		if (parameter.equals("PROBA_BIN")) {
			PROBA_BIN=Integer.parseInt(value);
		}
		if (parameter.equals("PROBA_FROM_COLOR")) {
			PROBA_FROM_COLOR = string2color(value);
		}
		if (parameter.equals("PROBA_TO_COLOR")) {
			PROBA_TO_COLOR = string2color(value);
		}
		if (parameter.equals("SINGLE_COMMON_COLOR")) {
			SINGLE_COMMON_COLOR = string2color(value);
		}
		if (parameter.equals("POS_COMMON_COLOR")) {
			POS_COMMON_COLOR = string2color(value);
		}
		if (parameter.equals("NEG_COMMON_COLOR")) {
			NEG_COMMON_COLOR = string2color(value);
		}
		if (parameter.equals("WITH_CHROM_NAME")) {
			WITH_CHROM_NAME = Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_COMMON_MARKER")) {
			WITH_COMMON_MARKER = Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_LEGEND")) {
			WITH_LEGEND= Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_MAP_NAME")) {
			WITH_MAP_NAME= Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_MARKER_NAME")) {
			WITH_MARKER_NAME= Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_QTL_NAME")) {
			WITH_QTL_NAME= Boolean.parseBoolean(value);
		}
		if (parameter.equals("WITH_MARKER_POSITION")) {
			WITH_MARKER_POSITION= Boolean.parseBoolean(value);
		}
		if (parameter.equals("LEGEND_GRAD_HEIGHT")) {
			LEGEND_GRAD_HEIGHT=Double.parseDouble(value);
		}
		if (parameter.equals("LEGEND_GRAD_WIDTH")) {
			LEGEND_GRAD_WIDTH=Double.parseDouble(value);
		}
	}
	/**
	 * @param value
	 * @return
	 */
	public static Color string2color(String value) {
		int[] rgb = parseRGB(value);
		return new Color(rgb[0],rgb[1],rgb[2]);
	}
	
	public static String color2string(Color color) {
		if (color == null) return new String("ffffff");
		String colStr=new String("");
		String rStr=Integer.toHexString(color.getRed());
		if (rStr.length()==1) colStr+="0"+rStr;
		else colStr+=rStr;
		String gStr=Integer.toHexString(color.getGreen());
		if (gStr.length()==1) colStr+="0"+gStr;
		else colStr+=gStr;
		String bStr=Integer.toHexString(color.getBlue());
		if (bStr.length()==1) colStr+="0"+bStr;
		else colStr+=bStr;
		return colStr;
	}
	/**
	 * @param value
	 * @return
	 */
	public static Font string2font(String value) {
		StringTokenizer tokenizer = new StringTokenizer(value,":",false);
		String fontName  = tokenizer.nextToken();
		String fontStyle = tokenizer.nextToken();
		int style = Font.PLAIN;
		if (fontStyle.equals("ITALIC")) {
			style=Font.ITALIC;
		} else if (fontStyle.equals("BOLD")) {
			style=Font.BOLD;
		}
		int size = Integer.parseInt(tokenizer.nextToken());
		return new Font(fontName, style, size);
	}
	/**
	 * 
	 * @param font
	 * @return
	 */
	public static String font2string(Font font) {
		String fontStr=font.getName();
		String styStr;
		switch(font.getStyle()) {
			case Font.ITALIC:
				styStr = new String(":ITALIC");
				break;
			case Font.BOLD:
				styStr =  new String(":BOLD");
				break;
			default :
				styStr =  new String(":PLAIN");
				break;
		}
		fontStr += styStr;
		fontStr += ":"+Integer.toString(font.getSize());
		return fontStr;
	}

	/**
	 * @param value
	 * @return
	 */
	private static int[] parseRGB(String value) {
		String r = value.substring(0, 2);
		String g = value.substring(2, 4);
		String b = value.substring(4, 6);
		int[] rgb = new int[3];
		rgb[0]=parseHexa(r);
		rgb[1]=parseHexa(g);
		rgb[2]=parseHexa(b);
		return  rgb;
	}
	/**
	 * 
	 * @param r
	 * @return
	 */
	private static int parseHexa(String hex) {
		return Integer.parseInt(hex, 16);
	}

	/**
	 * @param d
	 * @return
	 */
	public static Color getProbaColor(double d) {
		double h = 1.0/(double)PROBA_BIN;
		int cidx;
		if (d==1.0) cidx=PROBA_BIN-1;
		else  cidx = (int) Math.floor(d/h);
		return PROBA_PALETTE[cidx];
	}
	/**
	 * @param d
	 * @return
	 */
	public static Color getProbaColor(double d, double thresh) {
		if (d >= thresh)
			return PROBA_PALETTE[PROBA_BIN-1];
		else
			return PROBA_PALETTE[0];
	}
	/**
	 * 
	 *
	 */
	public static void initProbaPalette() {
		PROBA_PALETTE = PaletteColor.getPaletteGradient(PROBA_BIN, PROBA_FROM_COLOR, PROBA_TO_COLOR);
	}
	/**
	 * 
	 */
	public static void initQTLPalette() {
		if (QTL_COLOR_LIST == null || QTL_COLOR_LIST.size()<1) return;
		QTL_PALETTE = new Color[QTL_COLOR_LIST.size()];
		for(int i=0;i<QTL_PALETTE.length;i++)
			QTL_PALETTE[i]=(Color) QTL_COLOR_LIST.get(i);
	}
	/**
	 * 
	 *
	 */
	public static void initQTLPalette(int n) {
		QTL_PALETTE = PaletteColor.getPalette(n);
	}

	/**
	 * 
	 */
	public static void initPalettes() {
		initProbaPalette();
		initQTLPalette();
	}
	
}
