package org.postgresforest.tool.cli.action;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;

import org.postgresforest.tool.Logger;
import org.postgresforest.tool.lib.GSCdata;
import org.postgresforest.tool.lib.HashInfo;
import org.postgresforest.tool.util.CommandParser;
import org.postgresforest.tool.util.MessagesCommandLine;
import org.postgresforest.tool.util.Table2StringUtil;

/**
 * パーティション関数へのコマンドラインツール用のアクションを提供するクラス
 */
public class HashActions {

	private static final String[] SHOW_HASH_HEADER = {"HASHNAME","DESCRIPTION" }; //$NON-NLS-1$

	/**
	 * パーティション関数の作成
	 * @param cp コマンド解析結果
	 * @param gsc GSCヘの接続情報
	 */	
	public static void create(CommandParser cp, GSCdata gsc) {
		// ハッシュ関数の取得
		String className = cp.getHashName();
		if(className == null || className.equals("")){
			//引数が不正
			// FIXME:
			Logger.error("invalid argument.");
			return;
		}

		
		String fileName = cp.getHashFile();
		if(fileName == null || fileName.equals("")){
			//引数が不正
			// FIXME:
			Logger.error("invalid argument.");
			return;
		}

		//オプション取得
		String description = cp.getHashDescript(); //$NON-NLS-1$
		if ( description == null )
			description = "";
		
		// HashClassのバイトストリームの取得
		byte[] byteImg = null;
		try {
			byteImg = getFileByteImage(fileName);
		} catch (FileNotFoundException e) {
			Logger.error(MessagesCommandLine.getString("cui.error.command.filenotfound",
													   new Object[]{fileName})) ;
			Logger.error(e.getMessage());
			Logger.trace(e);
			return;
		} catch (Exception e1) {
			Logger.error(MessagesCommandLine.getString("cui.error.hash.create", new Object[]{className}));
			Logger.error(e1.getMessage());
			Logger.trace(e1);
			return;
		}		
		
		//HashLass登録
		if( gsc.registerHash(className, description, byteImg) ){
			Logger.println(MessagesCommandLine.getString("cui.message.hash.create", new Object[]{className})) ;
			return;	
			
		}

		Logger.error(MessagesCommandLine.getString("cui.error.hash.create", new Object[]{className}));
	}
	
	/**
	 * パーティション関数の削除
	 * @param cp コマンド解析結果
	 * @param gsc GSCヘの接続情報
	 */	
	public static void drop(CommandParser cp, GSCdata gsc) {
		String id = cp.getHashName();
		if(id == null || id.equals("")){
			//引数が不正
			// FIXME:
			Logger.error("invalid argument.");
			return;
		}

		
		//HashClass削除
		if( ! gsc.unregisterHash(id) ){
			
			Logger.error(MessagesCommandLine.getString("cui.error.hash.drop", new Object[] {id})) ;
			return;
			
		}

		Logger.println(MessagesCommandLine.getString("cui.message.hash.drop", new Object[] {id}));
	}

	/**
	 * パーティション関数の表示
	 * @param gsc GSCヘの接続情報
	 */	
	public static void show(GSCdata gsc) {

		String[] hashNames;

		//サーバ情報取得
		try {
			hashNames = gsc.getHashNames();
		} catch (Exception e) {
			Logger.error(MessagesCommandLine.getString("cui.error.hash.show"));
			Logger.error(e.getMessage());
			Logger.trace(e);
			return;
		}
		
		//Table情報表示
		Logger.println(MessagesCommandLine.getString("cui.message.hash.show")) ;
		Table2StringUtil table2StringUtil = new Table2StringUtil( SHOW_HASH_HEADER );

		if( hashNames != null){
			for (int i = 0; i < hashNames.length; i++) {
				HashInfo hashInfo = gsc.getHash(hashNames[i]);
				if(hashNames == null){
					//ハッシュ関数情報の取得失敗
					Logger.error(MessagesCommandLine.getString("cui.error.hash.show"));
					return;
				}
	
				ArrayList row = new ArrayList();
	
				row.add(hashInfo.getId());
				if ( hashInfo.getDescription()==null )
					row.add("");
				else
					row.add(hashInfo.getDescription());
	
				table2StringUtil.addRow(row);
				
			}
		}

		table2StringUtil.print();
		
	}
	
	/**
	 * @param fileName
	 * @return
	 * @throws FileNotFoundException
	 * @throws IOException
	 */
	private static byte[] getFileByteImage(String fileName) throws FileNotFoundException, IOException {
		byte[] buf = new byte[64];
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		FileInputStream in = new FileInputStream(fileName);

		int nBytes;

		while ((nBytes = in.read(buf)) > 0)
			out.write(buf, 0, nBytes);

		in.close();

		byte[] byteImg = out.toByteArray();
		out.close();
		return byteImg;
	}
}
