/*
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

/*
  <file> UlsOStream.cpp </file>
  <brief>
  </brief>
  <author>
    Stanley Hong <link2next@gmail.com>, April 2017.
  </author>
*/
#include "Stdafx.h"

#include "UlsOStream.h"
#include "UlsUtil.h"

using namespace System;
using namespace uls::util;

namespace uls {
namespace polaris {
	//
	// UlsOStream
	//
#define ULS_CLASS_NAME UlsOStream
	bool ULS_CLASS_NAME::makeOStream(String ^filepath, String ^subtag, bool numbering)
	{
		str2utf8bytes_t filepath_cpp(filepath);
		str2utf8bytes_t subtag_cpp(subtag);
		
		ohdr = uf->uls_create_ostream_file(filepath_cpp.cstr, uls_lex->getCore(), subtag_cpp.cstr);
		if (ohdr == nullptr) {
			Console::WriteLine("fail to create output stream object!");
			return false;
		}

		read_only = false;
		do_numbering = numbering;
		isDisposed = isFinalized = false;
#ifdef _MANAGE_ULS_OBJECTS
		addUlsObject2List(objs_list);
#endif
		return true;
	}

	ULS_CLASS_NAME::ULS_CLASS_NAME(String ^filepath, UlsLex ^lex, String ^subtag, bool numbering)
		: UlsStream(false)
	{
		uls_lex = lex;
		makeOStream(filepath, subtag, numbering);
	}

	ULS_CLASS_NAME::ULS_CLASS_NAME(String ^filepath, UlsLex ^lex, String ^subtag)
	{
		uls_lex = lex;
		makeOStream(filepath, subtag, true);
	}

	ULS_CLASS_NAME::ULS_CLASS_NAME(String ^filepath, UlsLex ^lex)
	{
		uls_lex = lex;
		makeOStream(filepath, gcnew String(""), true);
	}

	void ULS_CLASS_NAME::finalizer()
	{
		if (isFinalized) return;

		if (ohdr != nullptr) {
			uf->uls_destroy_ostream((UlsFactory::uls_ostream_t ^) ohdr);
			ohdr = nullptr;
		}

		isFinalized = true;
	}

	ULS_CLASS_NAME::~ULS_CLASS_NAME()
	{
		if (isDisposed) return;

		finalizer();
#ifdef _MANAGE_ULS_OBJECTS
		delUlsObject2List(objs_list);
#endif
		uls_lex = nullptr;
		isDisposed = true;
	}

	ULS_CLASS_NAME::!ULS_CLASS_NAME()
	{
		finalizer();
	}

	void ULS_CLASS_NAME::printTok(int tokid, String ^tokstr)
	{
		str2utf8bytes_t tokstr_cpp(tokstr);
		int rc;

		rc = uf->uls_print_tok(ohdr, tokid, tokstr_cpp.cstr);
		if (rc < 0) {
			Console::WriteLine("Can't a print token!");
		}
	}

	void ULS_CLASS_NAME::printTokLineNum(int lno, String ^tagstr)
	{
		str2utf8bytes_t tagstr_cpp(tagstr);
		int rc;

		rc = uf->uls_print_tok_linenum(ohdr, lno, tagstr_cpp.cstr);
		if (rc < 0) {
			Console::WriteLine("Can't a print linenum-token!");
		}
	}

	bool ULS_CLASS_NAME::startStream(UlsIStream ^ifile)
	{
		int rc, flags=0;

		if (ohdr == nullptr || read_only == true) {
			return false;
		}

		if (uls_lex->pushInput(ifile) == false)
		{
			return false;
		}

		if (do_numbering) {
			flags |= uf->_uls_const_LINE_NUMBERING();
		}

        if ((rc=uf->uls_start_stream(ohdr, flags)) < 0) {
            return false;
        }

        return true;
	}

	void ULS_CLASS_NAME::close()
	{
		if (ohdr != nullptr) {
			uf->uls_destroy_ostream((UlsFactory::uls_ostream_t ^) ohdr);
			ohdr = nullptr;
		}

		isDisposed = isFinalized = true;
	}

	UlsFactory::uls_ostream_t ^ULS_CLASS_NAME::getCoreHdr()
	{
		return ohdr;
	}

#undef ULS_CLASS_NAME

} // End of polaris
} // End of uls
