/* ////////// LICENSE INFO ////////////////////

 * Copyright (C) 2013 by NYSOL CORPORATION
 *
 * Unless you have received this program directly from NYSOL pursuant
 * to the terms of a commercial license agreement with NYSOL, then
 * this program is licensed to you under the terms of the GNU Affero General
 * Public License (AGPL) as published by the Free Software Foundation,
 * either version 3 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 EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF 
 * NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Please refer to the AGPL (http://www.gnu.org/licenses/agpl-3.0.txt)
 * for more details.

 ////////// LICENSE INFO ////////////////////*/
// =============================================================================
// kgcut.cpp 項目の選択クラス
// =============================================================================
#include <cstdio>
#include <vector>
#include <kgcut.h>
#include <kgError.h>
#include <kgConfig.h>

using namespace std;
using namespace kglib;
using namespace kgmod;

// -----------------------------------------------------------------------------
// コンストラクタ(モジュール名，バージョン登録,パラメータ)
// -----------------------------------------------------------------------------
kgCut::kgCut(void)
{
	#ifdef ENG_FORMAT
		#include <help/en/kgcutHelp.h>
	#else
		#include <help/jp/kgcutHelp.h>
	#endif
	_name    = "kgcut";
	_version = "1.0";
}

// -----------------------------------------------------------------------------
// 入出力ファイルオープン
// -----------------------------------------------------------------------------
void kgCut::setArgs(void)
{
	// パラメータチェック
	_args.paramcheck("f=,i=,o=,-r,-nfni");

	// -nfniを指定した場合、-xも指定されていることにする
	bool nfniflg = _args.toBool("-nfni");
	if(nfniflg){ 
		_nfn_i =nfniflg; 
		_fldByNum = true;
	}

	// 入出力ファイルオープン
	_iFile.open(_args.toString("i=",false), _env,_nfn_i);
	_oFile.open(_args.toString("o=",false), _env,_nfn_o);
	_iFile.read_header();

	// f= 項目引数のセット
	vector< vector<kgstr_t> > vvs = _args.toStringVecVec("f=",':',2,true);
	_fField.set(vvs, &_iFile, _fldByNum);

	// -r 出力反転フラグ
	_reverse = _args.toBool("-r");
}
// -----------------------------------------------------------------------------
// 単純にfldの内容を項目名として書き出す (利用mod: kgcutの-rなし)
// -----------------------------------------------------------------------------
void kgCut::writeFldName(kgArgFld& fld) throw(kgError) 
{
	if( _oFile.noFldName( ) ) return;

	size_t size=fld.size();
	if(fld.size()<=0){ throw kgError("no output fields"); }
	vector<kgstr_t> outfld;
	for(size_t i=0; i<size; i++){
		kgstr_t oName=fld.attr(i);            // second項目名
		if( oName.empty()) oName=fld.name(i); // second項目名がない時
		outfld.push_back( oName );
	}
	_oFile.writeFldNameCHK(outfld);
}

// -----------------------------------------------------------------------------
// fldの番号に対応するcsvの項目名を出力する．(利用mod: kgcutの-rあり)
//   ex. CSV a,b,c : fld=(1,3) : a,c
// -----------------------------------------------------------------------------
void kgCut::writeFldName(kgCSV& csv, const vector<int>& fld) throw(kgError) 
{
	if( _oFile.noFldName( ) ) return;

	vector<int>::size_type size=fld.size();
	if(fld.size()<=0){ throw kgError("no output fields"); }
	vector<kgstr_t> outfld;
	for(vector<int>::size_type i=0; i<size; i++){
		outfld.push_back( csv.fldName(fld[i]) );
	}
	_oFile.writeFldNameCHK(outfld);
}
// -----------------------------------------------------------------------------
// 実行
// -----------------------------------------------------------------------------
void kgCut::run(void) try 
{
	// パラメータセット＆入出力ファイルオープン
	setArgs();

	// 出力項目番号のセット
	vector<int> oField;
	if(! (_iFile.end() && _nfn_o) ){
		if(_reverse){
			for(size_t i=0; i<_iFile.fldSize(); i++){
				if( _fField.flg(i)==-1 ) oField.push_back(i);
			}
		}else{
			for(vector<kgstr_t>::size_type i=0; i<_fField.size(); i++){
				oField.push_back(_fField.num(i));
			}
		}
	}

	// 項目名出力
	if(_reverse) writeFldName(_iFile, oField);
	else         writeFldName(_fField);

	// データ出力
	while( EOF != _iFile.read() ){
		_oFile.writeFld(_iFile.getFld(),&oField);
	}

	// 終了処理
	_iFile.close();
	_oFile.close();
	successEnd();

// 例外catcher
}catch(kgError& err){
	errorEnd(err);
}
