/*  
 *  src/org/metaqtl/factory/EMResultFactory.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.factory;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.StringTokenizer;

import org.metaqtl.EMCriteria;
import org.metaqtl.EMResult;
import org.metaqtl.bio.util.NumberFormat;

/**
 *  
 */
public class EMResultFactory {
	
	public static EMResult read(BufferedReader buffer) throws IOException {
		if (buffer==null) return null;
		
		int n,k;
		StringTokenizer tokenizer;
		String line;
		EMResult emResult = new EMResult();
		
		n=0;
		
		while((line=buffer.readLine()) != null) {
			
			if (line.length() < 2) continue;
		
			switch(line.charAt(0)) {
				case 'C' :
					switch(line.charAt(1)) {
						case 'L' :
							tokenizer     = new StringTokenizer(line.substring(3));
							n 			  = Integer.parseInt(tokenizer.nextToken());
							k 			  = Integer.parseInt(tokenizer.nextToken());
							emResult      = new EMResult(n,k);
							emResult.olog = NumberFormat.parseDouble(tokenizer.nextToken());
							emResult.clog = NumberFormat.parseDouble(tokenizer.nextToken());
							n=k=0;
							break;
						case 'P' :
							tokenizer   = new StringTokenizer(line.substring(3));
							String type = tokenizer.nextToken();
							if (type.equals("MU")) {
								for(k=0;k<emResult.k;k++)
									emResult.mu[k] = NumberFormat.parseDouble(tokenizer.nextToken());
							} else if (type.equals("PI")) {
								for(k=0;k<emResult.k;k++)
									emResult.pi[k] = NumberFormat.parseDouble(tokenizer.nextToken());
							} else if (type.equals("CI")) {
								for(k=0;k<emResult.k;k++) {
									emResult.ocov[k][k]=NumberFormat.parseDouble(tokenizer.nextToken())/3.92;
									emResult.ocov[k][k]*=emResult.ocov[k][k];
								}
							} else if (type.equals("Z")) {
								tokenizer.nextToken();
								for(k=0;k<emResult.k;k++) {
									emResult.z[k][n] = NumberFormat.parseDouble(tokenizer.nextToken());								
								}
								n++;
								if (n==emResult.n) {
									//System.out.println("N " + n +" " +line);
									return emResult;
								}
							}
							break;
					    case 'C' :
					    	if (emResult.criteria == null)
					    		emResult.criteria = new EMCriteria();
					    	tokenizer=new StringTokenizer(line.substring(3));
					    	String criterion = tokenizer.nextToken();
					    	double value     = NumberFormat.parseDouble(tokenizer.nextToken());
					    	if (criterion.equals(EMCriteria.AIC_NAME))
					    		emResult.criteria.aic=value;
					    	else if (criterion.equals(EMCriteria.AIC3_NAME))
					    		emResult.criteria.aic3=value;
					    	else if (criterion.equals(EMCriteria.ICOMP_NAME))
					    		emResult.criteria.icomp=value;
					    	else if (criterion.equals(EMCriteria.BIC_NAME))
					    		emResult.criteria.bic=value;
					    	else if (criterion.equals(EMCriteria.AWE_NAME))
					    		emResult.criteria.awe=value;
					    	break;
					    default :
					    	break;
					}
					break;
				default :
					break;
			}
		}
		
		return emResult;
	}

	public static void write(EMResult result, OutputStream stream)
			throws IOException {
		if (result == null)
			return;
		if (stream == null)
			return;
		PrintWriter writer = new PrintWriter(stream);
		write(result, writer);
	}
	/**
	 * @param result
	 * @param writer
	 */
	public static void write(EMResult result, PrintWriter writer) {
		int k, n;
		writer.println("CL " + result.n + " " + result.k + " "
				+ NumberFormat.formatDouble(result.olog) + " "
				+ NumberFormat.formatDouble(result.clog));
		writer.println("CC " + EMCriteria.AIC_NAME + " " 
				+ NumberFormat.formatDouble(result.criteria.aic));
		writer.println("CC " + EMCriteria.AIC3_NAME + " "
				+ NumberFormat.formatDouble(result.criteria.aic3));
		writer.println("CC " + EMCriteria.ICOMP_NAME + " "
				+ NumberFormat.formatDouble(result.criteria.icomp));
		writer.println("CC " + EMCriteria.BIC_NAME + " "
				+ NumberFormat.formatDouble(result.criteria.bic));
		writer.println("CC " + EMCriteria.AWE_NAME + " "
				+ NumberFormat.formatDouble(result.criteria.awe));
		writer.print("CP PI ");
		for (k = 0; k < result.k - 1; k++) {
			writer.print(NumberFormat.formatDouble(result.pi[k]) + " ");
		}
		writer.println(NumberFormat.formatDouble(result.pi[k]));
		writer.print("CP MU ");
		for (k = 0; k < result.k - 1; k++) {
			writer.print(NumberFormat.formatDouble(result.mu[k]) + " ");
		}
		writer.println(NumberFormat.formatDouble(result.mu[k]));
		if (result.ocov != null) {
			writer.print("CP CI ");
			for (k = 0; k < result.k - 1; k++) {
				writer.print(NumberFormat.formatDouble(Math
						.sqrt(result.ocov[k][k]) * 3.92)
						+ " ");
			}
		}
		writer.println(NumberFormat.formatDouble(result.ocov[k][k]));

		for (n = 0; n < result.n; n++) {
			writer.print("CP Z " + n + " ");
			for (k = 0; k < result.k - 1; k++) {
				writer.print(NumberFormat.formatDouble(result.z[k][n]) + " ");
			}
			writer.println(NumberFormat.formatDouble(result.z[k][n]));
		}
		writer.flush();
	}

}