/*
 * Copyright (c) 2009, Takeyuki Nagao
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the
 * following conditions are met:
 * 
 *  * Redistributions of source code must retain the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the
 *    following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *    
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
 * OF SUCH DAMAGE.
 */

package jp.sourceforge.dvibrowser.dvicore;

/**
 * An immutable class to represent a range of bytes.
 * @author Takeyuki Nagao
 *
 */

public class DviByteRange
{
	public static final DviByteRange EMPTY = new DviByteRange();

  private final long begin;
  private final long end;

	private DviByteRange()
	{
	  begin = 0;
		end = -1;
	}

	public DviByteRange(long begin, long end)
	{
	  if (begin <= end) {
	    this.begin = begin;
		  this.end = end;
		} else {
	    this.begin = end;
		  this.end = begin;
		}
	}

	public long begin()
	{
	  return begin;
	}
	
	public long end()
	{
	  return end;
	}

	public DviByteRange translate(long by)
	{
	  return new DviByteRange(begin + by, end + by);
	}

	public DviByteRange intersect(DviByteRange a)
	{
	  if (a == null) return this;
	  if (this.isEmpty()) return EMPTY;
		if (a.isEmpty()) return EMPTY;
		long b = Math.max(this.begin, a.begin);
		long e = Math.min(this.end, a.end);
		return (b > e) ? EMPTY : new DviByteRange(b, e);
	}

	public DviByteRange union(DviByteRange a)
	{
	  if (a == null) return this;
	  if (this.isEmpty()) return a;
		if (a.isEmpty()) return this;
		return new DviByteRange(
		  Math.min(this.begin, a.begin),
		  Math.max(this.end, a.end)
		);
	}

	public boolean isEmpty()
	{
	  return this == EMPTY;
	}

	public long length()
	{
	  return end - begin + 1;
	}

	public boolean contains(long point)
	{
	  return (begin <= point && point <= end);
	}

	public boolean intersects(DviByteRange a)
	{
	  if (a == null) return false;
		return !this.intersect(a).isEmpty();
	}

	public String toString() {
	  return "" + begin + "--" + end;
	}
	public int hashCode() {
	  return (int)(begin + 33*end);
	}

	public boolean equals(Object obj) {
	  if (obj instanceof DviByteRange) {
		  DviByteRange br = (DviByteRange) obj;
			return br.begin == begin && br.end == end;
		}
		return false;
	}
}
