/*
    Scan Tailor - Interactive post-processing tool for scanned pages.
    Copyright (C) 2007-2015  Joseph Artsimovich <joseph.artsimovich@gmail.com>

    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef SPAN_H_
#define SPAN_H_

#include "foundation_config.h"

/**
 * \brief Represents a [from, to) range in one-dimensional space.
 */
class Span
{
public:
	/**
	 * \brief Constructs an empty span.
	 */
	Span() : m_begin(0), m_end(0) {}
	
	/**
	 * \brief Constructs a [begin, end) span.
	 */
	Span(int begin, int end) : m_begin(begin), m_end(end) {}
	
	/**
	 * \brief Constructs a span between a point and another span.
	 */
	Span(int begin, Span const& end)
	: m_begin(begin), m_end(end.begin()) {}
	
	/**
	 * \brief Constructs a span between another span and a point.
	 */
	Span(Span const& begin, int end)
	: m_begin(begin.end()), m_end(end) {}
	
	/**
	 * \brief Constructs a span between two other spans.
	 */
	Span(Span const& begin, Span const& end)
	: m_begin(begin.end()), m_end(end.begin()) {}
	
	int begin() const { return m_begin; }
	
	int end() const { return m_end; }
	
	int width() const { return m_end - m_begin; }
	
	double center() const { return 0.5 * (m_begin + m_end); }
	
	bool operator==(Span const& other) const {
		return m_begin == other.m_begin && m_end == other.m_end;
	}
	
	bool operator!=(Span const& other) const {
		return m_begin != other.m_begin || m_end != other.m_end;
	}
	
	Span& operator+=(int offset) {
		m_begin += offset;
		m_end += offset;
		return *this;
	}
	
	Span& operator-=(int offset) {
		m_begin -= offset;
		m_end -= offset;
		return *this;
	}
	
	Span operator+(int offset) const {
		Span span(*this);
		span += offset;
		return span;
	}
	
	Span operator-(int offset) const {
		Span span(*this);
		span -= offset;
		return span;
	}
private:
	int m_begin;
	int m_end;
};

#endif
