/*
 * Copyright (C) 2006 NTT DATA Corporation
 */
package org.postgresforest.tool.util;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
/**
 * テーブルデータ出力用ユーティリティ
 * ヘッダと各行のデータをオブジェクトの配列（リスト）で受け取り
 * 文字列によるテーブル表現を行う
 *
 */
public class Table2StringUtil {
	/**
	 * ヘッダ行（カラムの値Objectのリスト）
	 */
	private ArrayList m_Header;
	/**
	 * 行データ（カラム値のObjectのリストを持つリスト）
	 */
	private ArrayList m_Rows;
	/**
	 * カラムの出力幅
	 */
	private int[] m_colmunLengths;
	
	/**
	 * コンストラクタ 
	 * @param header　ヘッダ行データ（カラムの値Objectのリスト）
	 */
	public Table2StringUtil(ArrayList header) {
		m_Header = header;
		m_colmunLengths = new int[m_Header.size()];
		setColumnLength(m_Header);
		m_Rows = new ArrayList();
		
	}
	
	/**
	 * コンストラクタ 
	 * @param header　ヘッダ行データ（カラムの値Objectの配列）
	 */
	public Table2StringUtil(Object[] header) {

		this(new ArrayList(Arrays.asList(header)) );
	}


	/**
	 * 行追加 
	 * @param row　行データ（カラムの値Objectのリスト）
	 */
	public void addRow(ArrayList row){

		//カラム長取得
		setColumnLength(row);
		
		//行追加
		m_Rows.add(row);
		
		
	}
	/**
	 * 行追加 
	 * @param row　行データ（カラムの値Objectの配列）
	 */
	public void addRow(Object[] row){
		
		ArrayList listRow = new ArrayList(Arrays.asList(row));
		
		addRow(listRow);
	}
	/**
	 * 列の出力幅設定 
	 * @param row　行データ（カラムの値Objectのリスト）
	 */
	private void setColumnLength(ArrayList row) {
		//各列の値の文字列表現の長さを記憶
		for (int i = 0; i < m_colmunLengths.length; i++) {
			String column = String.valueOf(row.get(i));
			int lenb = getLenB(column);			
			if(lenb > m_colmunLengths[i])
				m_colmunLengths[i] =lenb;
		}
	}

	private int getLenB(String column) {
		int lenb = 0;
		for(int j=0;j<column.length();j++){
			char c = column.charAt(j);
			lenb += (c < 256) ? 1 : 2;
		}
		return lenb;
	}
	/**
	 * 行出力処理
	 * @param row	行データ（カラムの値Objectのリスト）
	 * @param hedear	true/false センタリンクを行う/行わない
	 * @return	区切り文字を入れた1行の文字列
	 */
	private String putLine(ArrayList row ,boolean hedear) {
		StringBuffer outPutStringBuffer = new StringBuffer();
		
		//カラム数分処理
		for (int i = 0; i < m_colmunLengths.length; i++) {
			//カラムの区切り文字出力
			if(i>0)
				outPutStringBuffer.append('|');

			//カラム先頭のスペース
			outPutStringBuffer.append(' ');

			//カラムの値取り出し
			Object value = row.get(i);
			String column = String.valueOf(value);
			
			//文字位置あわせ
			int fillLen = m_colmunLengths[i] - getLenB(column);
			char[] fill = new char[fillLen];
			Arrays.fill(fill ,' ');
			if(hedear){
				//センタリング
				int length = outPutStringBuffer.length();
				outPutStringBuffer.append(fill);
				outPutStringBuffer.insert( length + fillLen/2,column);
				
				
			}else{
				//センタリング以外は、オブジェクトの型で判断
				if (value instanceof Number) {
					//Number型は左寄せ
					outPutStringBuffer.append(fill);
					outPutStringBuffer.append(column);
				}else{
					//それ以外右寄せ
					outPutStringBuffer.append(column);
					outPutStringBuffer.append(fill);
				}
			}

			//カラムの最後のスペース
			outPutStringBuffer.append(' ');
		}
		return outPutStringBuffer.toString();
	}
	
	
	/**
	 * 文字列出力
	 */
	public String toString(){
		StringBuffer putString = new StringBuffer();

		//ヘッダー出力
		putString.append(putLine(m_Header,true));
		putString.append('\n');


		//ヘッダーライン出力
		char[] line = new char[putString.length()-1];

		Arrays.fill(line,'-');
		putString.append(line);
		putString.append('\n');

		//行出力
		for (Iterator iter = m_Rows.iterator(); iter.hasNext();) {
			ArrayList row = (ArrayList) iter.next();
			putString.append(putLine(row, false));
			putString.append('\n');
		}
		
		return putString.toString();
	}
	
	/**
	 * 標準出力への文字列出力
	 *
	 */
	public void print(){
		
		System.out.println(toString());
	}


}
