/* -*- mia-c++  -*-
 *
 * This file is part of MIA - a toolbox for medical image analysis 
 * Copyright (c) Leipzig, Madrid 1999-2017 Gert Wollny
 *
 * MIA is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License 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 WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with MIA; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#include <cassert>
#include <iomanip>
#include <mia/core/fixedwidthoutput.hh>

NS_MIA_BEGIN

using namespace std; 

CFixedWidthOutput::CFixedWidthOutput(std::ostream& os, size_t width):
	m_os(os), 
	m_width(width), 
	m_pos(0), 
	m_offset(0), 
	m_line_continue(false)
{
}

void CFixedWidthOutput::push_offset(size_t offset)
{
	m_stack.push(m_offset); 
	m_offset += offset;
}

void CFixedWidthOutput::pop_offset()
{
	assert(!m_stack.empty()); 
	m_offset = m_stack.top(); 
	m_stack.pop(); 
}

void CFixedWidthOutput::reset_offset()
{
	while (!m_stack.empty()) {
		m_stack.pop(); 
	}
	m_offset = 0;
}

void CFixedWidthOutput::set_linecontinue(bool value)
{
	m_line_continue = value; 
}

void CFixedWidthOutput::newline()
{
	if (m_line_continue) 
		m_os << '\\'; 
	m_os << std::endl; 
	if ( m_offset )
		m_os << setw(m_offset) << " "; 
	m_pos = m_offset;
}

void CFixedWidthOutput::write(const std::string& text)
{
	size_t cur_width = m_line_continue ? m_width -1 : m_width; 

	auto is = text.begin(); 
	auto es = text.end(); 

	while (is != es) {
		if (*is == '\n') {
			newline(); 
			++is;
		}else if (*is == '\t') {
			if (m_pos + 8 < cur_width) {
				m_pos += 8; 
				m_os << setw(8) << " "; 
			}else {
				newline(); 
			}
			++is; 
		}else if (isspace(*is)) {
			++m_pos;
			if (m_pos < cur_width) 
				m_os << *is; 
			else
				newline(); 
			++is; 
		}else {
			auto hs = is;
			size_t endpos = m_pos; 
			
			// search end of next word 
			while (hs != es && !isspace(*hs)) {
				++endpos;
				++hs; 
			}
			// word fits, so write it 
			if (endpos < cur_width) {
				m_pos = endpos; 
				while (is != hs) 
					m_os << *is++;
			}else { //  newline, tab and write word regardless of size 
				newline(); 
				while (is != hs) {
					m_os << *is++;
					++m_pos;
				}
			}
		}
	}
}

NS_MIA_END
