// File: gersteinlab[P]MUSIC/src/ms_annot_region_tools.cpp
// Function: merge_regions_per_super_regions(std::vector<t_annot_region*, std::allocator<t_annot_region*>>*, std::vector<t_annot_region*, std::allocator<t_annot_region*>>*)
vector<t_annot_region*>* merge_regions_per_super_regions(vector<t_annot_region*>* regions, vector<t_annot_region*>* super_regions)
{
	vector<t_annot_region*>* merged_regions = new vector<t_annot_region*>();

	for(int i_reg = 0; i_reg < (int)regions->size(); i_reg++)
	{
		regions->at(i_reg)->data = NULL;
	} // i_reg loop

	// Go over all the super regions, overlap them with regions, then merge the regions that overlap with the same super region.
	t_sorted_annot_region_lists* restructured_regions = restructure_annot_regions(regions);
	t_sorted_annot_region_lists* restructured_super_regions = restructure_annot_regions(super_regions);

	// Go over all the super regions.
	vector<t_annot_region*>* cur_regions = new vector<t_annot_region*>();

	for(int i_chr = 0; i_chr < (int)restructured_regions->chr_ids->size(); i_chr++)
	{
		vector<t_annot_region*>* cur_chrom_regions = restructured_regions->regions_per_chrom[i_chr];

		int i_sup_chr = t_string::get_i_str(restructured_super_regions->chr_ids, restructured_regions->chr_ids->at(i_chr));

		if(i_sup_chr < (int)restructured_super_regions->chr_ids->size())
		{			
			vector<t_annot_region*>* cur_chrom_super_regions = restructured_super_regions->regions_per_chrom[i_sup_chr];

			// Go over all the super regions, merge the regions that overlap with the same super region.
			for(int i_sup_reg = 0; i_sup_reg < (int)cur_chrom_super_regions->size(); i_sup_reg++)
			{
				// Find all the regions that are overlapping with the current super region.
				int i_left_reg = locate_posn_region_per_region_starts(cur_chrom_super_regions->at(i_sup_reg)->start, 
																		cur_chrom_regions, 0, (int)cur_chrom_regions->size()-1);

				while(i_left_reg > 0 &&
					cur_chrom_regions->at(i_left_reg)->end > cur_chrom_super_regions->at(i_sup_reg)->start)
				{
					i_left_reg--;
				}

				while(i_left_reg < (int)cur_chrom_regions->size() &&
					cur_chrom_regions->at(i_left_reg)->start < cur_chrom_super_regions->at(i_sup_reg)->end)
				{
					int ol_start = MAX(cur_chrom_regions->at(i_left_reg)->start, cur_chrom_super_regions->at(i_sup_reg)->start);
					int ol_end = MIN(cur_chrom_regions->at(i_left_reg)->end, cur_chrom_super_regions->at(i_sup_reg)->end);

					// Check the overlap.
					if(ol_end >= ol_start)
					{
						cur_regions->push_back(cur_chrom_regions->at(i_left_reg));

						// Sanity check: Make sure whole region is contained in the super region.
						if(cur_chrom_regions->at(i_left_reg)->end > cur_chrom_super_regions->at(i_sup_reg)->end ||
							cur_chrom_regions->at(i_left_reg)->start < cur_chrom_super_regions->at(i_sup_reg)->start)
						{
							fprintf(stderr, "Sanity check failed: Region: %d-%d, Super-region: %d-%d\n", 
								cur_chrom_regions->at(i_left_reg)->start, cur_chrom_regions->at(i_left_reg)->end, 
								cur_chrom_super_regions->at(i_sup_reg)->start, cur_chrom_super_regions->at(i_sup_reg)->end);

							exit(0);
						}
					}

					i_left_reg++;
				} // i_left_reg loop.

				if(cur_regions->size() > 0)
				{
					sort(cur_regions->begin(), cur_regions->end(), sort_regions);

					// Merge all the regions in the overlapping regions.
					t_annot_region* cur_merged_region = get_empty_region();
					cur_merged_region->chrom = t_string::copy_me_str(cur_regions->at(0)->chrom);
					cur_merged_region->strand = cur_regions->at(0)->strand;
					cur_merged_region->start = cur_regions->at(0)->start;
					cur_merged_region->end = cur_regions->back()->end;
					merged_regions->push_back(cur_merged_region);

					// Clear and delete current regions.
					cur_regions->clear();
				}				
			} // i_sup_reg loop.
		} // i_sup_chr check.
		else
		{
			fprintf(stderr, "Could not find %s in super regions list.\n", restructured_regions->chr_ids->at(i_chr));

			// Add all the regions in this chromosome.
			for(int i_reg = 0; i_reg < (int)cur_chrom_regions->size(); i_reg++)
			{
				t_annot_region* cur_merged_region = duplicate_region(cur_chrom_regions->at(i_reg));
				merged_regions->push_back(cur_merged_region);
			} // i_reg loop.
		}
	} // i_chr loop.

	return(merged_regions);
}

// Assembly:
subq $0x128, %rsp            # imm = 0x128
movq %rdi, 0x120(%rsp)
movq %rsi, 0x118(%rsp)
movl $0x18, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, 0x90(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x2110
movq 0x90(%rsp), %rdi
callq 0xc670
movq 0x90(%rsp), %rax
movq %rax, 0x110(%rsp)
movl $0x0, 0x10c(%rsp)
movl 0x10c(%rsp), %eax
movl %eax, 0x8c(%rsp)
movq 0x120(%rsp), %rdi
callq 0xc680
movq %rax, %rcx
movl 0x8c(%rsp), %eax
cmpl %ecx, %eax
jge 0x29c0c
movq 0x120(%rsp), %rdi
movslq 0x10c(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movq $0x0, 0x48(%rax)
movl 0x10c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x10c(%rsp)
jmp 0x29bb0
movq 0x120(%rsp), %rdi
callq 0x29200
movq %rax, 0x100(%rsp)
movq 0x118(%rsp), %rdi
callq 0x29200
movq %rax, 0xf8(%rsp)
movl $0x18, %edi
callq 0x2190
movq %rax, %rdi
movq %rdi, 0x80(%rsp)
xorl %esi, %esi
movl $0x18, %edx
callq 0x2110
movq 0x80(%rsp), %rdi
callq 0xc670
movq 0x80(%rsp), %rax
movq %rax, 0xf0(%rsp)
movl $0x0, 0xec(%rsp)
movl 0xec(%rsp), %eax
movl %eax, 0x7c(%rsp)
movq 0x100(%rsp), %rax
movq 0x18(%rax), %rdi
callq 0xc220
movq %rax, %rcx
movl 0x7c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a384
movq 0x100(%rsp), %rax
movq (%rax), %rax
movslq 0xec(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0xe0(%rsp)
movq 0xf8(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x70(%rsp)
movq 0x100(%rsp), %rax
movq 0x18(%rax), %rdi
movslq 0xec(%rsp), %rsi
callq 0xc240
movq 0x70(%rsp), %rdi
movq (%rax), %rsi
callq 0x47cf0
movl %eax, 0xdc(%rsp)
movl 0xdc(%rsp), %eax
movl %eax, 0x78(%rsp)
movq 0xf8(%rsp), %rax
movq 0x18(%rax), %rdi
callq 0xc220
movq %rax, %rcx
movl 0x78(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a2b1
movq 0xf8(%rsp), %rax
movq (%rax), %rax
movslq 0xdc(%rsp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, 0xd0(%rsp)
movl $0x0, 0xcc(%rsp)
movl 0xcc(%rsp), %eax
movl %eax, 0x6c(%rsp)
movq 0xd0(%rsp), %rdi
callq 0xc680
movq %rax, %rcx
movl 0x6c(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a2ac
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x5c(%rsp)
movq 0xe0(%rsp), %rax
movq %rax, 0x60(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc680
movl 0x5c(%rsp), %edi
movq 0x60(%rsp), %rsi
movl %eax, %ecx
subl $0x1, %ecx
xorl %edx, %edx
callq 0x297a0
movl %eax, 0xc8(%rsp)
xorl %eax, %eax
cmpl $0x0, 0xc8(%rsp)
movb %al, 0x5b(%rsp)
jle 0x29e30
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x54(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x54(%rsp), %eax
movq (%rcx), %rcx
cmpl 0xc(%rcx), %eax
setg %al
movb %al, 0x5b(%rsp)
movb 0x5b(%rsp), %al
testb $0x1, %al
jne 0x29e3a
jmp 0x29e4d
movl 0xc8(%rsp), %eax
addl $-0x1, %eax
movl %eax, 0xc8(%rsp)
jmp 0x29dd8
jmp 0x29e4f
movl 0xc8(%rsp), %eax
movl %eax, 0x4c(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc680
movl 0x4c(%rsp), %ecx
movl %eax, %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, 0x53(%rsp)
jge 0x29ebf
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x48(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x48(%rsp), %eax
movq (%rcx), %rcx
cmpl 0x20(%rcx), %eax
setl %al
movb %al, 0x53(%rsp)
movb 0x53(%rsp), %al
testb $0x1, %al
jne 0x29ecc
jmp 0x2a17c
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x44(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x44(%rsp), %eax
movq (%rcx), %rcx
cmpl 0xc(%rcx), %eax
jle 0x29f30
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x40(%rsp)
jmp 0x29f4f
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x40(%rsp)
movl 0x40(%rsp), %eax
movl %eax, 0xc4(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x3c(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x3c(%rsp), %eax
movq (%rcx), %rcx
cmpl 0x20(%rcx), %eax
jge 0x29fbe
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x38(%rsp)
jmp 0x29fdd
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x38(%rsp)
movl 0x38(%rsp), %eax
movl %eax, 0xc0(%rsp)
movl 0xc0(%rsp), %eax
cmpl 0xc4(%rsp), %eax
jl 0x2a166
movq 0xf0(%rsp), %rax
movq %rax, 0x28(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq 0x28(%rsp), %rdi
movq %rax, %rsi
callq 0xc8c0
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x34(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x34(%rsp), %eax
movq (%rcx), %rcx
cmpl 0x20(%rcx), %eax
jg 0x2a0b5
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x24(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq %rax, %rcx
movl 0x24(%rsp), %eax
movq (%rcx), %rcx
cmpl 0xc(%rcx), %eax
jge 0x2a164
movq 0x3af24(%rip), %rax     # 0x64fe0
movq (%rax), %rax
movq %rax, 0x10(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x18(%rsp)
movq 0xe0(%rsp), %rdi
movslq 0xc8(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, 0x1c(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %eax
movl %eax, 0x20(%rsp)
movq 0xd0(%rsp), %rdi
movslq 0xcc(%rsp), %rsi
callq 0xc800
movq 0x10(%rsp), %rdi
movl 0x18(%rsp), %edx
movl 0x1c(%rsp), %ecx
movl 0x20(%rsp), %r8d
movq (%rax), %rax
movl 0x20(%rax), %r9d
leaq 0x2bba0(%rip), %rsi     # 0x55cf6
movb $0x0, %al
callq 0x2250
xorl %edi, %edi
callq 0x21f0
jmp 0x2a166
movl 0xc8(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xc8(%rsp)
jmp 0x29e4f
movq 0xf0(%rsp), %rdi
callq 0xc680
cmpq $0x0, %rax
jbe 0x2a294
movq 0xf0(%rsp), %rdi
callq 0xc7d0
movq %rax, 0xb8(%rsp)
movq 0xf0(%rsp), %rdi
callq 0xc760
movq %rax, 0xb0(%rsp)
movq 0xb8(%rsp), %rdi
movq 0xb0(%rsp), %rsi
leaq 0x1cc(%rip), %rdx       # 0x2a3a0
callq 0x31d00
callq 0x27b00
movq %rax, 0xa8(%rsp)
movq 0xf0(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xc800
movq (%rax), %rax
movq (%rax), %rdi
callq 0x47b60
movq %rax, %rcx
movq 0xa8(%rsp), %rax
movq %rcx, (%rax)
movq 0xf0(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xc800
movq (%rax), %rax
movb 0x8(%rax), %cl
movq 0xa8(%rsp), %rax
movb %cl, 0x8(%rax)
movq 0xf0(%rsp), %rdi
xorl %eax, %eax
movl %eax, %esi
callq 0xc800
movq (%rax), %rax
movl 0xc(%rax), %ecx
movq 0xa8(%rsp), %rax
movl %ecx, 0xc(%rax)
movq 0xf0(%rsp), %rdi
callq 0x1b3d0
movq (%rax), %rax
movl 0x20(%rax), %ecx
movq 0xa8(%rsp), %rax
movl %ecx, 0x20(%rax)
movq 0x110(%rsp), %rdi
leaq 0xa8(%rsp), %rsi
callq 0xc8c0
movq 0xf0(%rsp), %rdi
callq 0x31d90
jmp 0x2a296
movl 0xcc(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xcc(%rsp)
jmp 0x29d5c
jmp 0x2a36c
movq 0x3ad28(%rip), %rax     # 0x64fe0
movq (%rax), %rax
movq %rax, 0x8(%rsp)
movq 0x100(%rsp), %rax
movq 0x18(%rax), %rdi
movslq 0xec(%rsp), %rsi
callq 0xc240
movq 0x8(%rsp), %rdi
movq (%rax), %rdx
leaq 0x2ba47(%rip), %rsi     # 0x55d2f
movb $0x0, %al
callq 0x2250
movl $0x0, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0x4(%rsp)
movq 0xe0(%rsp), %rdi
callq 0xc680
movq %rax, %rcx
movl 0x4(%rsp), %eax
cmpl %ecx, %eax
jge 0x2a36a
movq 0xe0(%rsp), %rdi
movslq 0xa4(%rsp), %rsi
callq 0xc800
movq (%rax), %rdi
callq 0x2a410
movq %rax, 0x98(%rsp)
movq 0x110(%rsp), %rdi
leaq 0x98(%rsp), %rsi
callq 0xc8c0
movl 0xa4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xa4(%rsp)
jmp 0x2a2fa
jmp 0x2a36c
jmp 0x2a36e
movl 0xec(%rsp), %eax
addl $0x1, %eax
movl %eax, 0xec(%rsp)
jmp 0x29c7f
movq 0x110(%rsp), %rax
addq $0x128, %rsp            # imm = 0x128
retq
nopw %cs:(%rax,%rax)