/*
    libmaus2
    Copyright (C) 2016 German Tischler

    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/>.
*/
#include <libmaus2/lcs/AlignmentOneAgainstManyFactory.hpp>

#if 0
static std::string numString(uint64_t const from, uint64_t const to)
{
	std::string s(to-from,'\0');

	for ( uint64_t i = 0; i < s.size(); ++i )
		s[i] = from+i;

	return s;
}
#endif

#include <vector>
#include <libmaus2/lcs/NP.hpp>

int main()
{
	std::vector<std::string> V;
	#if 0
	for ( uint64_t i = 0; i < 5; ++i )
		V.push_back(numString(i*11,(i+1)*11));

	V[0][5] = 7;

	std::string q = numString(0,11);
	#endif

	#if 0
	std::string const q = "TAAGATCAATATTTCGTAAGGTTGTAAATATTTGTGGTTTACCTTCTGACGACTTTCTGCTTAAACAGGGTTCAATTTGATTATTAC";
	V.push_back(std::string("TAAGATCCAATGATTTTCGTAAGTTGTAACATATTTGTTGGTATTACCTTCCTCGACCGACTTTCTTGCTTAATACGGGGTTCTAAATTTGATTTATTAC"));
	V.push_back(std::string("TAAGATCAATATTTCGTAAGGTTTGTAAATATTCTGTGGTTTACCTGTCTGACGAGCTTATCTGCTGTAAACAAGGGTCTCAATTTATTATTAAT"));
	V.push_back(std::string("TAAGATTCAATATTATCGTAAGGTTGTAAATATTTGTGGTTTACCTTCTGACGACTTTCGCGTTAACAGGGTGTCAATTTGATATTAC"));
	V.push_back(std::string("TAAGATTCAATGATTTCGGTAAGGTTGTAAAAATAGTTTGTGAGTTTACCTTCTCGACGACTTTCTGCTTAAACCGGTGTTCAATTTGATTAGTTAC"));
	V.push_back(std::string("TAAGGATCAATATTTCGTTAAGGTTGTAGAATATTTGTCTGTTTTACCTTCTGACGAACTTTCTGCTTAAACAGGGTTCAATTTGATTATTAC"));
	V.push_back(std::string("AAAGATGCATATATTTCCGTAAAGGTTGTAATAATATTGTGGTTTACCTTCTTGTAACGACTTTCTGCTCTAAACAGGGTTCATATGTTGATTATTTAC"));
	V.push_back(std::string("TAAGTATTCAATATTTCGTAGGTTGTAAATATGTTGTGGTTTACCTTCGTGACGACTTTTCTGCTAAATCAGGGTTCATATTTGGATTATTAC"));
	V.push_back(std::string("TAAGATCAAATATTTCGTAAGGTTGTAAATATTTGTTGGTTTAACCTTCTGACGACTTTCTGCCTTGAAACACGGTTTCAATTGTTGATGATTTAAC"));
	V.push_back(std::string("TTAAGTATCAAATATTTTCGTTAAGGTTGTAAATATTCTGTGGTTTACCTCTCTGACGAGCTTTCCTGCTTAAACAGGGTTCAATTTGATTATCT"));
	V.push_back(std::string("TCAGATCAATGAGTTTCGTAAGGGTTGTAAATATTTGTGAGTTTACCTTACTGACGACTTTCTGCTTAAACAGGGTATACAATTTGATTATTCT"));
	V.push_back(std::string("TAAGATCATATTTTCGTAAGGTTGTAAATATTTGTGGTTTACCTCTCGAGCGACTTTCTGTGTTCAAACAGGGTTGTCCAATTTTGATTATTAC"));
	V.push_back(std::string("TAAGATCATATATTGTCGTAAGGGTTGTAAATATTTTGTGGTTTACCTTCCTGACGACTTTTGCTTAAACCAGGTGTTCAATTTGTGATATATTAC"));
	V.push_back(std::string("TAGATCAATATTTCGTAGAGTTGTCAAATATTATGTGGGTTTGACCTTCTGACGACTCTTGCGACTGTACAACACGGTGTTCAATTTGATTTGACTTCT"));
	V.push_back(std::string("TAAGATCAATTTTTTCGTAAGGTTGTAATATTTGTGGTTATTACCTGGCTCGACGGACTTTCTTCTTAAACAGGGTTCAATATAATGATTACTTAC"));
	V.push_back(std::string("TAAGATCGAATGATTTCGTGAAGGTTGTAATATATTTGTGGTTTACCTTCTAGACGACATTTCTTGCTTAAACAGGGTTCAAGTTTGATTAATTAC"));
	V.push_back(std::string("TAAGATCAAATATTTCTGTAAGGGTTGTTAATGATTTGATAGGTTTACCCTTCTGACGACTTTCTGCATTAGAACAGGGTGTTCAATTTGAATTATTAC"));
	V.push_back(std::string("TAAGATCAACTATTTCGTAAGGTTGTGAAGATATTTCTGGTTTATGCCTTCTTGACAGACTTTCTGCTTAAACACGGCGTTTAATTTCGATTATTAC"));
	V.push_back(std::string("CAAGATCCAATTGATTTCAGTAAGGTTAGTAAATATTTGTAGGTTTACACTTCTGACGACTTTCTGGGCTTAACGAGGGCGTTCAAATTTGATTATTAC"));
	V.push_back(std::string("TACAGATCAATATTTCGTAGAGGTTGTAAATATCTTGTTTGTTTACCCTTCAGCACGACTATTCTGCCCTAAAGCAGGGTTCAACTTTGATTATTAC"));
	V.push_back(std::string("TAAGATTCCATATCATTTCCTAAGTTTGTAGAATATTTGTTGTTTACCATTTCTGGCGACTTTTCTGCTGAAAACAGGGTTCAATTTTGGATTATTAC"));
	V.push_back(std::string("TAAGATCAATATTTCGTAAGGTTGGAAATATTTGTGGTTTACCCCTTCTGACGATTTCTGCTTAGAACAGGGTATCAACTTTGATTATTAC"));
	V.push_back(std::string("TAAGACAATATTTCGTTAAGGTTGTAAATAATTTGTGGTTTACCTGGTCGTGACGTACTTTCTGCTTGAAACAGGGTTCAATTTGAACTTATTAC"));
	V.push_back(std::string("TAAGATCAGATAGCTTTCGCTAGAGGCTTGTATATTTGTGGTTACCTTCTGACGACTTTCTTTGCTTAAAACAGGGTTCAATTTTGATTATTAC"));
	V.push_back(std::string("TAAGATCCAATTTTCGTAAGGTTGTAAATATTATGTGAGTTTACTTGCTGACGCACTTTTCTGCATAAACAGGGCTTTCAATTTGATTATTAC"));
	V.push_back(std::string("TAAGATCAATATTCTTACGTACAGGTTGTAAATATTTGTGGTTTGACCTTCTGACGACTTTCTGCTTAAACAGGGTTCAATTATCGATTATTAC"));
	V.push_back(std::string("TAAGATCAATATTTCGGTAAGGTCTTAAATATTTGTGGTTTACCTTCTGACGACTTTCTGCTTTAAACAGGGGTTCAATTTGATTATTAC"));
	V.push_back(std::string("TAAGATCCAATATTTCGTAAGGTCTGGTAAATTTGTGGTTTACACTTCTGACGACATCTCGTGCTTAACAGGAGTTCAATTTGATTATTTACTTAG"));
	#endif

	std::string const q="TTCCGCTGATATCCACTTTCCTGACCATCACCCCTTCATCGTATTCCGGGGGCGTTGTGTTGCCGCTGTACTGCCGCGCTGACGGCTGATACCGCG";
	V.push_back(std::string("TTCCGCTGATATCCACTTTCCTACCACACCCCTTCATCGTAATTCCGCGGGGGCCGTTGTGTTGCCGCTGTACTGCCGCAGCTGACCGCCTGTCACCGCG"));
	V.push_back(std::string("TTCCGCTGAATACCACTTTTCCTGGACCATCACTCCCTGTCATCGCAATCCGGGGGCGTGTGTTGCCGCTCGTACTCGCCGGCGGCTGATCGGCTGATATCTCGCG"));
	V.push_back(std::string("TTCCGCATGATATCCACGTTTCCTGACCATCACCCCTTCATCGTTATTCCGCGGGGGCGTTGTGTTCTGCTCGCCTGTAACTTGCCGCGCTGACGGCTGAATACCGCG"));
	V.push_back(std::string("TTCACGCCTTGATATCCACTTTCCTGGACACATCACCCCCTCACGTATTTCCGGAGGGCGTTGTGCTAGTCCCTGTACTAGCCTGCGCTGGCGGCTGATCCACCCGGCG"));
	V.push_back(std::string("TTCCGCTGCATATCTCACGTTCCTGACTATCACCCCTCATCGTATTTCCGGGGGGCGTTGTGGTCTTGTCGCGCTCTGTACTGCCGCGCCCTGCACTGCTGATGACCGCG"));
	V.push_back(std::string("TTTCCCGTGCTGGGATATCGCACGTTCTCCTCCCATCGAACCATCACCGCCTTCATCGGATTCCGGGGCAGCCGTATGCCTGTTGCCCGCCTGTACTGACTCGGCCTGAAACAGGCTGATACCGGCTG"));
	V.push_back(std::string("TTCCGCTGAATATGCCACTTTCCATGAACCATCACCCCTTCATCGTACTTCCGGGGGACGTTGTGTTGCCGGCTTGTATGCCCGCGCTAGACGGTCCTGATACCGCAG"));
	V.push_back(std::string("TTCCGCTGAATATCCACTTTCCTGAGCCAATCCACCCCCTTCAGTCCGTATTCCGGGGGCTGTTGGTGTTTGCCTGCTGTACTTGCCGCGCTGACGGGCTGATACCGCTG"));
	V.push_back(std::string("TTCCGCTTAATATCCACTTTACCTGACCATCACCCCTTTTCATCGATATTACAGGGGGCCGTTGTGGTTGCCGCTGTACTGCTCGCGCTGATCGGCTGAATACCTGCG"));
	V.push_back(std::string("CTCCGCCTGATATCCACTTTGCCTGACCATCACCCCTTCAGTCGTATTTCCGGGGGCGTTTGTAGTTGCCTGCTGTACTACTGCCGCGGCTGAGGCTGAATACCGCG"));
	V.push_back(std::string("TTCCGCTGATATCCACTTTCCTGACCATCAACTGCCCTTCGATCGTATTCCGGGGGCGTTGTGTTGCCGCTGTACTGCCGCGCTGATCTGGCTGATACCGCG"));
	V.push_back(std::string("TCCTCTGATATCCCACTCTTTCCTGACCATCCCCCCTTCATTCGTATTTCCGGGGGCGTTTGTGTTTGCCGCTGTATGCCCGCGCTGACGGTGATACTCGCG"));
	V.push_back(std::string("TTCCCCGCTGATATCCATCGTTTCCTGACCCAGTCACCCCTTCATCGTATTCCGGCGGGCCGTGTGTGTTTGGCCGCATGTACTGCCGCTGACTGACGGCTGATACCGCG"));
	V.push_back(std::string("ATTCCGCTGATATCCACTTCCTTGAACCATCACCCCTTCGATTCGCTAATGCGCGGAGAGCGTTGTGTTGCCGACTGTACTGCCGCGCTGACGGCTGATACCCTGACG"));
	V.push_back(std::string("CTCCCGCCTGATATGCCACCTTTGCACTGACTCATCACGCCCTTCTCGTTATTCCGGGGGCGTTGTGTCTGCCGCTGTTCTGACCGCGCTGAGGCGACTAGATATCCGCTG"));
	V.push_back(std::string("TTCCGCCTGATATCCACTTTCCTGACCATCACTCCCCTTCATCGTATTCCGGGGAGCGTTGTGTTGGCCGGCGTGTACTGCCGCGCTGAACGGGCTGATACCGCG"));
	V.push_back(std::string("TTCCGCTGATATTCCACTTTCCTGACCATCACCCCTCTCATCGTAGTTCCGGGGGCGTTGGTCGTTGCCGCTGTACTGCCGCGCTGACGGCTGATTACCGCG"));
	V.push_back(std::string("TTCCGCTGACTATCAACTTCTCCCTGACCATCGCCCCTTCATCGTATTGCCGGGGGCGTTGTAGTTTGCCACTGTACTGCTGCGCTGACGGCTGATACCGCAG"));
	V.push_back(std::string("TTCCCTGATATCCACCTATTCCTGCACCAATCACCGCCTATCATACGTATCCGGGGGCGTTGTGTTGGCCGCATGCTACTGCTCAGCGCTGTACGGGCTGAACCAGCTG"));
	V.push_back(std::string("TTCCGCCTGATATCCACTTTCCTGACCATCACCCCGTTCATCGTATTCCGGGGGTTGTGCTTGCAGCGCTGGTAACTGCCGCGCTGACGGCTGATACCGCG"));
	V.push_back(std::string("TTCCGCTGATATCCACTTTCCTGACCATTCACCCCCTTCAACGTATTCCGGGGGCGTTGTGTTCCGCTCGCACTGCCGCGCTGACGGCTGATACCGCG"));
	V.push_back(std::string("TTTCCGCTGATATCCACTTTCCTGAACCATCCCCCCTTCATCGTATTCCCGGGCGGCGTTGTGTTGGCGCTCTACTCGCCGCGCTGACGGCTGATACCGCG"));
	V.push_back(std::string("TTCCGCTGATATCCACTATCCTTAGACCCAATCACCCCCTGTCATCGTCATTGGCCGGGGGCGCTTGTGTACTGCCCGCCTGTACTGCCGCGCTTGGACGGCTGATACCGCG"));
	V.push_back(std::string("TTCCGGTGTATCATACCTAACTTTCCTGACCATCACCTCCTTCATCGTATTTGCCGGGGGCGATTGTGTTGCCGTCTGTAGTGCCCGGGCTGAACCGGCGCTGATACCGCG"));
	V.push_back(std::string("TTCCGCTGATATCCCACTTGTCCTGACCTATCACCCCTTCATCGTATTCCGGGGCGCGTTGTGTGCCGCTGTACTGCCGCGCTTGACGGACTGATTACCGCG"));
	V.push_back(std::string("TTACGGCTGATATCCTACTTTCCTGACCTACTCACCCCCTTCGATCGTAGTTCCGGGGGCGTTGGGTGTTGCCGCTGTACTGCCCTGCGCTGACCGGGCTGATACCGCG"));
	V.push_back(std::string("TTCCGCATGATATCCACTTTCCTGACCATGCACCTCCTTCATCGTAGTTCCGCGGGGCGTTGTCGTTGCCGCTTGTACTGCCGTCGCTGACGGCAGTGATCAACCGCG"));
	V.push_back(std::string("TTTCACTGCTAGATATCCACTTTCACTAGACCATCACCCCTTCATCGTACTTCCGGGGGCGTTGTGTTGCCGTCTTGGTACTGGCCGCGCTGCATCGGCTGATACCGTCG"));
	V.push_back(std::string("TTCCGCTGTATATCCACTTTCCTTTGACCATTCAACCCCCTTTCAATCGTATTACGCGGGGGCGTTGTGTTCGCCGCTGGCTACTGCCGCGCTGGACGGCTCGATACTCGGCG"));
	V.push_back(std::string("TTCCGCTGATATCCACTTTCCTACCATCGACACACCTTCATACCGTATTCCGCGAGGGCGTTGGTGTTTGCCGCTGTACTGCCGACGCTGACGGCATGATAGCTCGCTG"));
	V.push_back(std::string("TTCCGCTGACTATCCACTTTTCCTTGACACATCACCCCTTCATCGTATTCCGGGGGCGTTGTGTTGCCGCTGTACTGCCTGCGCTGACAGGCTGATCACCGCG"));
	V.push_back(std::string("ATTCCGCTGATATCTCACTTTCCCTGACCATCACCCCTTCCATCGTATTCCGGGGGCGTTGCTGTTGCCGCTCATGTCACTGCCGCGCGACGGCTGTATACCGCG"));
	V.push_back(std::string("TTCCTGGTGATATCCCACTTATTCCTGACCAATCACCCCTTCACGTATTCCGGGGGCGTTGTGTTGCCGCTGTGCTGCCGCGCCGACGGCGTGATACGCGCG"));


	uint8_t const * qa = reinterpret_cast<uint8_t const *>(q.c_str());
	uint8_t const * qe = qa + q.size();

	typedef std::pair<uint8_t const *, uint64_t> up;
	libmaus2::autoarray::AutoArray < up > U(V.size());
	for ( uint64_t i = 0; i < V.size(); ++i )
	{
		char const * c = V[i].c_str();
		uint8_t const * u = reinterpret_cast<uint8_t const *>(c);
		U[i] = up(u,V[i].size());
	}

	libmaus2::autoarray::AutoArray<uint64_t> E;
	libmaus2::lcs::AlignmentOneAgainstManyInterface::unique_ptr_type aligner(
		libmaus2::lcs::AlignmentOneAgainstManyFactory::uconstruct()
	);
	aligner->process(qa,qe,U.begin(),U.size(),E);
	for ( uint64_t i = 0; i < U.size(); ++i )
	{
		std::cerr << "U[" << i << "]=" << E[i] << std::endl;
		libmaus2::lcs::NP np;

		np.align(qa,qe-qa,U[i].first,U[i].second);
                assert ( E[i] == np.getTraceContainer().getAlignmentStatistics().getEditDistance());
	}

	#if 0
	uint8_t A[] __attribute__((aligned(sizeof(LIBMAUS2_SIMD_WORD_TYPE)))) = {
		0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
		16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
	};
	__m256i i = LIBMAUS2_SIMD_LOAD_ALIGNED(reinterpret_cast<LIBMAUS2_SIMD_WORD_TYPE const *>(&A[0]));
	std::cerr << formatRegister(i) << std::endl;
	#endif
}
