/********************************************************************/
/* Copyright (c) 2019 System fugen G.K. and Yuzi Mizuno          */
/* All rights reserved.                                             */
/********************************************************************/
/********************************************************************/
#include "StdAfx.h"
#include "mg/Group.h"
#include "mg/MGStl.h"
#include "fugen.h"
#include "IO/GLStlExporter.h"
#include "IO/util.h"

#include "GLStlSaveOptionDlg.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

// コンストラクター
CGLStlExporter::CGLStlExporter()
	 : CGLFileExporter(IDS_FILTER_STL),
	   m_bSaveAscii(true),
	   m_bSingle(false)
{
}

// group に含まれる MGStl オブジェクトのみを保存する。
//
// MGStl ごとにファイルを作成する可能性がある。
// ファイル名には適当に連番が付く。
bool CGLStlExporter::Save(const MGGroup& group)
{
	const CString strFileName = GetFileName();
	// ファイル読み込み処理

	// MGStl のみを抽出する。
	// ただし、トップの階層にある要素だけテストする。
	std::vector<const MGStl*> stls;
	MGGroup::const_iterator first = group.begin(), last = group.end();
	for(; first != last; ++first){
		if(const MGStl* pStl = dynamic_cast<const MGStl*>(first->get())){
			stls.push_back(pStl);
		}
	}
	if(stls.empty()){
		CString str, strMsg;
		VERIFY(strMsg.LoadString(IDS_MESH_NOT_EXIST));
		str.Format(IDS_WARNING, strMsg);
		COUT << (TCAST)str << std::endl;
		return false;
	}

	const bool bSaveAscii = m_bSaveAscii;

	const size_t nMesh = stls.size();
	if(nMesh == 1){
		return SaveStl(*stls.front(), strFileName, bSaveAscii);
	}

	if(m_bSingle){
		return SaveStlSingle(stls, strFileName);
	}

	// 名前をつけつつ SaveNas
	bool bAllOk = true;
	for(size_t i = 0; i < nMesh; ++i){
		CString strSavePath = AddNumberToPath(strFileName, _T("-%02d"), i);
		if(SaveStl(*stls[i], strSavePath, bSaveAscii)){
			bAllOk = false;
		}
	}

	return bAllOk;
}

// group に含まれる MGStl オブジェクトのみを保存する。
//
// MGStl ごとにファイルを作成する可能性がある。
// ファイルが複数の場合は00から連番が付く。
// ファイル名は引数で指定可能とする。
// また、saveしたファイル数を返却する
bool CGLStlExporter::Save(const MGGroup& group, const CString fileName, int& fileNum)
{
	const CString strFileName = fileName;
	// ファイル読み込み処理

	// MGStl のみを抽出する。
	// ただし、トップの階層にある要素だけテストする。
	std::vector<const MGStl*> stls;
	MGGroup::const_iterator first = group.begin(), last = group.end();
	for(; first != last; ++first){
		if(const MGStl* pStl = dynamic_cast<const MGStl*>(first->get())){
			stls.push_back(pStl);
		}
	}
	if(stls.empty()){
		CString str, strMsg;
		VERIFY(strMsg.LoadString(IDS_MESH_NOT_EXIST));
		str.Format(IDS_WARNING, strMsg);
		putInOutputWindow(str);
		return false;
	}

	const bool bSaveAscii = m_bSaveAscii;
	const size_t nMesh = stls.size();
	fileNum = 0;
	if(nMesh == 1){
		fileNum++;
		return SaveStl(*stls.front(), strFileName, bSaveAscii, false);
	}

	if(m_bSingle){
		fileNum++;
		return SaveStlSingle(stls, strFileName);
	}

	// 名前をつけつつ SaveNas
	bool bAllOk = true;
	for(size_t i = 0; i < nMesh; ++i){
		CString strSavePath = AddNumberToPath(strFileName, _T("-%02d"), i);
		if(SaveStl(*stls[i], strSavePath, bSaveAscii, false)){
			bAllOk = false;
			fileNum++;
		}
	}
	return bAllOk;
}

/// true を返す。
bool CGLStlExporter::HasOption() const
{
	return true;
}

/// ダイアログを表示して、メンバーデータを設定する。
void CGLStlExporter::DoShowOptionDialog()
{
	CGLStlSaveOptionDlg dlg;
	dlg.SetBinary(!m_bSaveAscii);
	dlg.SetSingle(m_bSingle);
	
	if(dlg.DoModal() != IDOK){
		return;
	}

	m_bSaveAscii = !dlg.IsBinary();
	m_bSingle = dlg.IsSingle()==TRUE;
}

// STL ファイルに保存する。
bool SaveStl(const MGStl& stl, const CString& strFileName, bool bSaveAscii, bool bOutputInfo /* =true */)
{
	bool bOk = true;
	if(bSaveAscii){
		std::ofstream fout(strFileName);
		bOk = stl.SaveAscii(fout) == 0;
	}
	else{
		bOk = stl.SaveBinary(strFileName) == 0;
	}

	CString str, strMsg;
	if(bOk){
		if (bOutputInfo){
			strMsg.Format(IDS_SAVE_SUCCESS, strFileName);
			str.Format(IDS_INFORMATION, strMsg);
		}
	}
	else{
		strMsg.Format(IDS_SAVE_FAILURE, strFileName);
		str.Format(IDS_ERROR, strMsg);
	}
	if (str != "")
		putInOutputWindow(str);

	return bOk;
}

// 複数メッシュを単一の STL ファイルに保存する。
bool SaveStlSingle(const std::vector<const MGStl*>& stls, const CString& strFilePath)
{
	std::ofstream fout(strFilePath);
	if(!fout){
		CString str, strMsg;
		strMsg.Format(IDS_SAVE_FAILURE_WRITE, strFilePath);
		str.Format(IDS_ERROR, strMsg);
		putInOutputWindow(str);
		return false;
	}

	// 格納されているMGStlオブジェクトごとにファイルに出力する
	bool bSaved = true;
	size_t nObj = stls.size();
	for(size_t j = 0; j < nObj; j++){
		const MGStl& stli = *stls[j];
		if(!stli.SaveAscii(fout)){
			bSaved = false;
		}
	}

	CString str, strMsg;
	if(bSaved){
		strMsg.Format(IDS_SAVE_SUCCESS, strFilePath);
		str.Format(IDS_INFORMATION, strMsg);
	}
	else{
		CString str, strMsg;
		strMsg.Format(IDS_MESH_FAILURE_PARTIAL, strFilePath);
		str.Format(IDS_WARNING, strMsg);
		putInOutputWindow(str);
	}

	return bSaved;
}
