// File: karel-brinda[P]ococo/src/caller.h
// Function: ococo::caller_t<unsigned short, 3, 4>::caller_t(ococo::params_t*)
caller_t<T, counter_size, refbase_size>::caller_t(params_t *params_)
    : params(params_) {
    /*
     * Read SAM headers.
     */

	t_real = realtime();
    ococo::info("Initialing SAM/BAM reader.\n");

    correctly_initialized = true;
    return_code           = EXIT_SUCCESS;

    iter   = nullptr;
    b      = nullptr;
    header = nullptr;
    stats  = nullptr;

    params->sam_file = sam_open(params->sam_fn.c_str(), "r");
    if (params->sam_file == nullptr) {
        ococo::fatal_error("Problem with opening SAM/BAM file ('%s').\n",
                           params->sam_fn.c_str());
        correctly_initialized = false;
        return;
    }

    if ((header = sam_hdr_read(params->sam_file)) == 0) {
        ococo::fatal_error("SAM/BAM headers are missing or corrupted.\n");
        correctly_initialized = false;
        return;
    }

    stats = new (std::nothrow)
        stats_t<T, counter_size, refbase_size>(params, *header);
    if (stats == nullptr || !stats->check_allocation()) {
        ococo::fatal_error("Allocation of the main structure failed.\n");
        correctly_initialized = false;
        return;
    }

    /*
     * Load FASTA and stats.
     */

    if (!params->stats_in_fn.empty() && !params->fasta_in_fn.empty()) {
        ococo::fatal_error(
            "Initial FASTA reference and input statistics "
            "cannot be used at the same time.\n");
        correctly_initialized = false;
        return;
    }

    if (!params->stats_in_fn.empty()) {
        ococo::info("Loading statistics ('%s').\n",
                    params->stats_in_fn.c_str());

        int error_code = stats->import_stats(params->stats_in_fn);
        if (error_code != 0) {
            ococo::fatal_error("Import of statistics failed (file '%s').\n",
                               params->stats_in_fn.c_str());
            correctly_initialized = false;
            return;
        }
    } else {
        if (!params->fasta_in_fn.empty()) {
            ococo::info("Loading reference ('%s').\n",
                        params->fasta_in_fn.c_str());

            int error_code = stats->load_fasta(params->fasta_in_fn);
            if (error_code != 0) {
                ococo::fatal_error("Loading of FASTA failed (file '%s').\n",
                                   params->fasta_in_fn.c_str());
                correctly_initialized = false;
                return;
            }
        }

        else {
            ococo::info(
                "Neither reference, nor statistics provided. Going "
                "to "
                "consider sequence of N's as a reference.\n");
        }
    }

    /*
     * Open VCF file.
     */

    if (params->vcf_fn.size() > 0) {
        ococo::info("Opening VCF stream ('%s').\n", params->vcf_fn.c_str());

        if (params->vcf_fn == std::string("-")) {
            params->vcf_file = stdout;
        } else {
            params->vcf_file = fopen(params->vcf_fn.c_str(), "w+");
            if (params->vcf_file == nullptr) {
                ococo::fatal_error("Problem with opening VCF file '%s'.\n",
                                   params->vcf_fn.c_str());
                correctly_initialized = false;
                return;
            }
        }

        char buf[PATH_MAX + 1];
        char *res = realpath(params->fasta_in_fn.c_str(), buf);
        std::string fasta_full_path;
        if (res) {
            fasta_full_path = std::string(buf);
        } else {
            fasta_full_path = params->fasta_in_fn;
        }

        stats->print_vcf_header(params->vcf_file, params->command,
                                fasta_full_path);
    }

    /*
     * Open pileup file.
     */

    if (params->pileup_fn.size() > 0) {
        ococo::info("Opening pileup stream ('%s').\n",
                    params->pileup_fn.c_str());

        if (params->pileup_fn == std::string("-")) {
            params->pileup_file = stdout;
        } else {
            params->pileup_file = fopen(params->pileup_fn.c_str(), "w+");
            if (params->pileup_file == nullptr) {
                ococo::fatal_error("Problem with opening pileup file '%s'.\n",
                                   params->pileup_fn.c_str());
                correctly_initialized = false;
                return;
            }
        }
    }

    /*
     * Open consensus FASTA file.
     */

    if (params->fasta_out_fn.size() > 0) {
        params->fasta_out_file = fopen(params->fasta_out_fn.c_str(), "w+");

        ococo::info("Opening consensus file ('%s').\n",
                    params->fasta_out_fn.c_str());
        params->fasta_out_file = fopen(params->fasta_out_fn.c_str(), "w+");

        if (params->fasta_out_file == nullptr) {
            ococo::fatal_error(
                "Problem with opening FASTA for consensus: '%s'.\n",
                params->fasta_out_fn.c_str());
            correctly_initialized = false;
            return;
        }
    }

    /*
     * Open log file.
     */

    if (params->log_fn.size() > 0) {
        params->log_file = fopen(params->log_fn.c_str(), "w+");

        ococo::info("Opening log file ('%s').\n", params->log_fn.c_str());
        params->log_file = fopen(params->log_fn.c_str(), "w+");

        if (params->log_file == nullptr) {
            ococo::fatal_error("Problem with opening log file: '%s'.\n",
                               params->log_fn.c_str());
            correctly_initialized = false;
            return;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1180, %rsp           # imm = 0x1180
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x1120(%rbp)
movq -0x10(%rbp), %rcx
movq %rcx, 0x28(%rax)
callq 0xf6f0
movq -0x1120(%rbp), %rax
movsd %xmm0, 0x30(%rax)
leaq 0x725b2(%rip), %rdi     # 0x78090
movb $0x0, %al
callq 0xf5e0
movq -0x1120(%rbp), %rax
movb $0x1, (%rax)
movl $0x0, 0x4(%rax)
movq $0x0, 0x8(%rax)
movq $0x0, 0x10(%rax)
movq $0x0, 0x18(%rax)
movq $0x0, 0x20(%rax)
movq 0x28(%rax), %rdi
addq $0x78, %rdi
callq 0x4200
movq %rax, %rdi
leaq 0x75ec2(%rip), %rsi     # 0x7b9ef
callq 0x13260
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x198(%rcx)
movq 0x28(%rax), %rax
cmpq $0x0, 0x198(%rax)
jne 0x5b89
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x78, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x72539(%rip), %rdi     # 0x780ac
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rax
movq 0x198(%rax), %rdi
callq 0x1cfe0
movq -0x1120(%rbp), %rcx
movq %rax, 0x18(%rcx)
cmpq $0x0, %rax
jne 0x5bce
leaq 0x7251f(%rip), %rdi     # 0x780d7
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
movl $0x38, %edi
movq 0x843c6(%rip), %rsi     # 0x89fa0
callq 0x4b60
movq %rax, %rcx
movq %rcx, -0x1130(%rbp)
movb $0x0, -0x19(%rbp)
xorl %eax, %eax
cmpq $0x0, %rcx
movq %rax, -0x1128(%rbp)
je 0x5c31
movq -0x1130(%rbp), %rdi
movq -0x1120(%rbp), %rax
movq %rdi, -0x18(%rbp)
movb $0x1, -0x19(%rbp)
movq 0x18(%rax), %rdx
movq 0x28(%rax), %rsi
callq 0x8dd0
jmp 0x5c21
movq -0x1130(%rbp), %rax
movq %rax, -0x1128(%rbp)
jmp 0x5c31
movq -0x1120(%rbp), %rax
movq -0x1128(%rbp), %rcx
movq %rcx, 0x20(%rax)
cmpq $0x0, 0x20(%rax)
je 0x5c5e
movq -0x1120(%rbp), %rax
movq 0x20(%rax), %rdi
callq 0x9440
testb $0x1, %al
jne 0x5ca4
leaq 0x7249d(%rip), %rdi     # 0x78102
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
testb $0x1, -0x19(%rbp)
jne 0x5c8f
jmp 0x5c9f
movq -0x18(%rbp), %rdi
movq 0x84306(%rip), %rsi     # 0x89fa0
callq 0x4320
jmp 0x6526
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xb8, %rdi
callq 0x49c0
testb $0x1, %al
jne 0x5cf7
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x98, %rdi
callq 0x49c0
testb $0x1, %al
jne 0x5cf7
leaq 0x7244b(%rip), %rdi     # 0x7812c
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xb8, %rdi
callq 0x49c0
testb $0x1, %al
jne 0x5d9e
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xb8, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x72444(%rip), %rdi     # 0x7817b
movb $0x0, %al
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x20(%rax), %rdi
movq 0x28(%rax), %rsi
addq $0xb8, %rsi
callq 0x94d0
movl %eax, -0x30(%rbp)
cmpl $0x0, -0x30(%rbp)
je 0x5d99
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xb8, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x72414(%rip), %rdi     # 0x78197
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x5e52
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x98, %rdi
callq 0x49c0
testb $0x1, %al
jne 0x5e42
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x98, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x723e3(%rip), %rdi     # 0x781c1
movb $0x0, %al
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x20(%rax), %rdi
movq 0x28(%rax), %rsi
addq $0x98, %rsi
callq 0x9790
movl %eax, -0x34(%rbp)
cmpl $0x0, -0x34(%rbp)
je 0x5e40
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x98, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x723b2(%rip), %rdi     # 0x781dc
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x5e50
leaq 0x723b9(%rip), %rdi     # 0x78202
movb $0x0, %al
callq 0xf5e0
jmp 0x5e52
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xe0, %rdi
callq 0x43a0
cmpq $0x0, %rax
jbe 0x6193
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xe0, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x723cd(%rip), %rdi     # 0x78261
xorl %eax, %eax
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rax
addq $0xe0, %rax
movq %rax, -0x1140(%rbp)
leaq -0x59(%rbp), %rdi
movq %rdi, -0x1138(%rbp)
callq 0x4a50
movq -0x1138(%rbp), %rdx
leaq 0x723ac(%rip), %rsi     # 0x7827d
leaq -0x58(%rbp), %rdi
callq 0x9bf0
jmp 0x5edc
movq -0x1140(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x9b60
movb %al, -0x1141(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x4340
leaq -0x59(%rbp), %rdi
callq 0x45f0
movb -0x1141(%rbp), %al
testb $0x1, %al
jne 0x5f10
jmp 0x5f4b
movq -0x1120(%rbp), %rax
movq 0x8407a(%rip), %rcx     # 0x89f98
movq (%rcx), %rcx
movq 0x28(%rax), %rax
movq %rcx, 0x180(%rax)
jmp 0x5fcd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x59(%rbp), %rdi
callq 0x45f0
jmp 0x6526
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xe0, %rdi
callq 0x4200
movq %rax, %rdi
leaq 0x72313(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x180(%rcx)
movq 0x28(%rax), %rax
cmpq $0x0, 0x180(%rax)
jne 0x5fcb
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0xe0, %rdi
callq 0x4200
movq %rax, %rsi
leaq 0x722cd(%rip), %rdi     # 0x78282
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x5fcd
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x98, %rdi
callq 0x4200
movq %rax, %rdi
leaq -0x1060(%rbp), %rsi
callq 0x41b0
movq %rax, -0x1068(%rbp)
leaq -0x1088(%rbp), %rdi
callq 0x47e0
cmpq $0x0, -0x1068(%rbp)
je 0x6089
leaq -0x10a9(%rbp), %rdi
movq %rdi, -0x1150(%rbp)
callq 0x4a50
movq -0x1150(%rbp), %rdx
leaq -0x10a8(%rbp), %rdi
leaq -0x1060(%rbp), %rsi
callq 0x9bf0
jmp 0x603f
leaq -0x1088(%rbp), %rdi
leaq -0x10a8(%rbp), %rsi
callq 0x46f0
leaq -0x10a8(%rbp), %rdi
callq 0x4340
leaq -0x10a9(%rbp), %rdi
callq 0x45f0
jmp 0x60bc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x10a9(%rbp), %rdi
callq 0x45f0
jmp 0x6182
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rsi
addq $0x98, %rsi
leaq -0x1088(%rbp), %rdi
callq 0x4060
jmp 0x60a9
jmp 0x60bc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6182
movq -0x1120(%rbp), %rax
movq 0x20(%rax), %rcx
movq %rcx, -0x1160(%rbp)
movq 0x28(%rax), %rsi
movq 0x180(%rsi), %rax
movq %rax, -0x1158(%rbp)
addq $0x8, %rsi
leaq -0x10d0(%rbp), %rdi
callq 0x4220
jmp 0x60f2
leaq -0x10f0(%rbp), %rdi
leaq -0x1088(%rbp), %rsi
callq 0x4220
jmp 0x6107
movq -0x1158(%rbp), %rsi
movq -0x1160(%rbp), %rdi
leaq -0x10d0(%rbp), %rdx
leaq -0x10f0(%rbp), %rcx
callq 0x9ca0
jmp 0x612a
leaq -0x10f0(%rbp), %rdi
callq 0x4340
leaq -0x10d0(%rbp), %rdi
callq 0x4340
leaq -0x1088(%rbp), %rdi
callq 0x4340
jmp 0x6193
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
jmp 0x6176
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x10f0(%rbp), %rdi
callq 0x4340
leaq -0x10d0(%rbp), %rdi
callq 0x4340
leaq -0x1088(%rbp), %rdi
callq 0x4340
jmp 0x6526
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x43a0
cmpq $0x0, %rax
jbe 0x6322
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x4200
movq %rax, %rsi
leaq 0x720d2(%rip), %rdi     # 0x782a7
xorl %eax, %eax
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rax
addq $0x140, %rax            # imm = 0x140
movq %rax, -0x1170(%rbp)
leaq -0x1111(%rbp), %rdi
movq %rdi, -0x1168(%rbp)
callq 0x4a50
movq -0x1168(%rbp), %rdx
leaq 0x72068(%rip), %rsi     # 0x7827d
leaq -0x1110(%rbp), %rdi
callq 0x9bf0
jmp 0x6223
movq -0x1170(%rbp), %rdi
leaq -0x1110(%rbp), %rsi
callq 0x9b60
movb %al, -0x1171(%rbp)
leaq -0x1110(%rbp), %rdi
callq 0x4340
leaq -0x1111(%rbp), %rdi
callq 0x45f0
movb -0x1171(%rbp), %al
testb $0x1, %al
jne 0x6260
jmp 0x629e
movq -0x1120(%rbp), %rax
movq 0x83d2a(%rip), %rcx     # 0x89f98
movq (%rcx), %rcx
movq 0x28(%rax), %rax
movq %rcx, 0x188(%rax)
jmp 0x6320
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
leaq -0x1111(%rbp), %rdi
callq 0x45f0
jmp 0x6526
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x4200
movq %rax, %rdi
leaq 0x71fc0(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x188(%rcx)
movq 0x28(%rax), %rax
cmpq $0x0, 0x188(%rax)
jne 0x631e
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x140, %rdi            # imm = 0x140
callq 0x4200
movq %rax, %rsi
leaq 0x71fbe(%rip), %rdi     # 0x782c6
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x6320
jmp 0x6322
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0x43a0
cmpq $0x0, %rax
jbe 0x6421
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0x4200
movq %rax, %rdi
leaq 0x71f1b(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x190(%rcx)
movq 0x28(%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0x4200
movq %rax, %rsi
leaq 0x71f56(%rip), %rdi     # 0x782ee
movb $0x0, %al
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0x4200
movq %rax, %rdi
leaq 0x71ebf(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x190(%rcx)
movq 0x28(%rax), %rax
cmpq $0x0, 0x190(%rax)
jne 0x641f
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x100, %rdi            # imm = 0x100
callq 0x4200
movq %rax, %rsi
leaq 0x71f05(%rip), %rdi     # 0x7830e
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x6421
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x43a0
cmpq $0x0, %rax
jbe 0x651d
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x4200
movq %rax, %rdi
leaq 0x71e1c(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x1a0(%rcx)
movq 0x28(%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x4200
movq %rax, %rsi
leaq 0x71ea8(%rip), %rdi     # 0x7833f
movb $0x0, %al
callq 0xf5e0
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x4200
movq %rax, %rdi
leaq 0x71dc0(%rip), %rsi     # 0x7827f
callq 0x4690
movq %rax, %rdx
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rcx
movq %rdx, 0x1a0(%rcx)
movq 0x28(%rax), %rax
cmpq $0x0, 0x1a0(%rax)
jne 0x651b
movq -0x1120(%rbp), %rax
movq 0x28(%rax), %rdi
addq $0x160, %rdi            # imm = 0x160
callq 0x4200
movq %rax, %rsi
leaq 0x71e51(%rip), %rdi     # 0x78359
movb $0x0, %al
callq 0xf3a0
movq -0x1120(%rbp), %rax
movb $0x0, (%rax)
jmp 0x651d
jmp 0x651d
addq $0x1180, %rsp           # imm = 0x1180
popq %rbp
retq
movq -0x28(%rbp), %rdi
callq 0x4a30
nop