/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

#include <iostream>
#include <fstream>
#include <vector>
#include <haplotype.h>

int
main()
{
	ifstream is("test/haplotype.test");
	Haplotype a;
	cout << "Reading a..."; cout.flush();
	is >> a;
	cout << "done" << endl;
	cout << "a should be " << "( 11 22 33 44 55 66 77 88 )" << endl;
	cout << "a:          " << a << endl;
	cout << "a is not latent (should be 0): " << (a.IsLatent() ? 1 : 0)
	     << endl;
	a.Mask(2, 6);
	cout << "a should be " << "( NA NA 33 44 55 66 NA NA )" << endl;
	cout << "a:          " << a << endl;
	cout << "a is not latent (should be 0): " << (a.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;
	Haplotype b;
	b.ReadDelimited(is, Haplotype::DISEASED);
	cout << "b should be " << "( 111 222 333 444 555 666 777 )" << endl;
	cout << "b:          " << b << endl;
	cout << "b is not latent (should be 0): " << (b.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;
	Haplotype c;
	c.ReadDelimited(is, Haplotype::DISEASED);
	cout << "c should be " << "( 77 66 55 44 33 22 11 [L] )" << endl;
	cout << "c:          " << c << endl;
	cout << "c is latent (should be 1): " << (c.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;
	Haplotype l;
	is >> l;
	cout << "l should be " << "( 3 1 4 1 5 9 [L] )" << endl;
	cout << "l:          " << l << endl;
	cout << "l is latent (should be 1): " << (l.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;
	Haplotype n;
	is >> n;
	cout << "n should be " << "( 2 4 6 8 10 12 [L] [N] )" << endl;
	cout << "n:          " << n << endl;
	cout << "n is latent (should be 1): " << (n.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;
	Haplotype nl;
	is >> nl;
	cout << "nl should be " << "( 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [N] )" << endl;
	cout << "nl:          " << nl << endl;
	cout << "nl is not latent (should be 0): " << (nl.IsLatent() ? 1 : 0)
	     << endl;

	cout << endl;

	vector<Marker> loci;
	for (int i = 0; i < 10; ++i)
		loci.push_back(i);

	Haplotype h(loci.size());
	for (unsigned int i = 0; i < loci.size(); ++i)
		h.Mutate(i, loci[i]);
	Haplotype x = h;
	Haplotype y(h);

	cout << "Should be the same:" << endl;
	cout << "h: " << h << endl;
	cout << "x: " << x << endl;
	cout << "y: " << y << endl;
	cout << endl;

	h.Mutate(0, 99);
	x.Mutate(1, 99);
	y.Mutate(2, 99);

	cout << "Should all be different at loci 0, 1, 2:" << endl;
	cout << "h: " << h << endl;
	cout << "x: " << x << endl;
	cout << "y: " << y << endl;
	cout << endl;

	Haplotype s = h.Substr(5, 8);
	cout << "    should be " << "( 5 6 7 [L] )" << endl;
	cout << "s = h[5, 8) = " << s << endl;
	cout << "s is latent (should be 1): " << (s.IsLatent() ? 1 : 0)
	     << endl;

	Haplotype::const_iterator i, j;
	i = h.begin();
	++i; ++i; ++i;
	j = h.end();
	Haplotype t(i, j);
	cout << "     should be " << "( 3 4 5 6 7 8 9 [L] )" << endl;
	cout << "t = h[3, 10) = " << t << endl;
	cout << "t is latent (should be 1): " << (t.IsLatent() ? 1 : 0)
	     << endl;

	Haplotype v = h.Substr(i, j);
	cout << "v should equal t" << endl;
	cout << "v = " << v << endl;

	Haplotype u = h.Substr(5, 10);
	cout << "     should be " << "( 5 6 7 8 9 [L] )" << endl;
	cout << "u = h[5, 10) = " << u << endl;
	cout << endl;

	cout << "h < u: " << (h < u) << " (should be 0)" << endl;
	cout << "u < h: " << (u < h) << " (should be 1)" << endl;
	cout << "h == u: " << (h == u) << " (should be 0)" << endl;
	cout << endl;

	Haplotype nullHaplotype = Haplotype();
	cout << "nullHaplotype: " << nullHaplotype << endl;
	cout << "nullHaplotype is latent (should be 1): "
		<< (nullHaplotype.IsLatent() ? 1 : 0) << endl;
	cout << "Test if empty haplotype equals anything else (shouldn't)."
		 << endl;
	cout << "null < u: " << (nullHaplotype < u) << endl;
	cout << "u < null: " << (u < nullHaplotype) << endl;
	cout << "null == u: " << (nullHaplotype == u) << endl;
	cout << endl;

	return 0;
}
