#!/usr/bin/python3
"""
circle_check.py

Copyright (c) 2017-2018 Guanliang Meng <mengguanliang@foxmail.com>.

This file is part of MitoZ.

MitoZ 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.

MitoZ 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 MitoZ.  If not, see <http://www.gnu.org/licenses/>.

"""

import sys
from Bio import SeqIO

usage = """
Description

    Checking whether the sequences are circular when the sequences have
    length >= 12Kbp

Usage

    python3 {0}  <in.fasta>  <outfile> <mismatch_allowed>

output files:
if the sequences is not circular, then all the three files will be empty.

1. <outfile>
The circular mt sequence, with the overlapping region (the second `ATGCNN`
below) has been removed.

ATGCNNNNN[ATGCNN]

Assuming `ATGCNNNNN` is a circular mt sequence, `ATGCNN` are the overlapping
regions.

2. <outfile>.start2end
Same as <outfile>, except that the first 300 bp has been moved to the end
of the sequence, just for better reads mapping. You can check the sequencing
depth around the 'joining site' (-300 bp) using the `annotate` module of
MitoZ, to confirm if the sequence is really circular.

3. <outfile>.overlap_information
The overlapping sequence detected.

""".format(sys.argv[0])

if len(sys.argv) != 4:
    print(usage)
    sys.exit(0)

in_f, out_f, mismatch_allowed = sys.argv[1:4]
mismatch_allowed = int(mismatch_allowed)

def seq_distance(seq1=None, seq2=None):
    if len(seq1) != len(seq2):
        print(seq1)
        print(seq2)
        sys.exit("Error: seq1 and seq2 have different lengths!")

    seq1 = seq1.upper()
    seq2 = seq2.upper()

    mismatch = 0
    for i in range(0, len(seq1)):
        if seq1[i] != seq2[i]:
            mismatch += 1
    return (mismatch)

fh_out = open(out_f, 'w')
fh_out2 = open(out_f+'.overlap_information', 'w')
fh_out3 = open(out_f+".start2end", 'w')
for rec in SeqIO.parse(in_f, 'fasta'):
    seq = str(rec.seq)
    seqlen = len(seq)
    if seqlen < 12000:
        continue

    potential_seq = seq[12000:]
    overlap_len = 5
    match_start_pos = 0
    tmp = 0
    while(1):
        subseq_5 = seq[0:overlap_len]
        match_count = potential_seq.count(subseq_5)
        if match_count > 1:
            overlap_len += 1
        elif match_count == 1:
            match_start_pos = 12000 + potential_seq.find(subseq_5)
            #print("first: ", subseq_5)
            break
        else:
            print("not found!")
            tmp = 1
            break

    if tmp == 1:
        continue

    start_pos = match_start_pos
    overlap_seq = ""
    for i in range(0, int(seqlen/2)):
        subseq_5 = seq[0:overlap_len]
        stop_pos = match_start_pos + overlap_len
        if stop_pos <= len(seq):
            subseq_3 = seq[start_pos:stop_pos]
            # print(subseq_5)
            # print(subseq_3)
            if seq_distance(subseq_5, subseq_3) < mismatch_allowed:
                overlap_seq = subseq_5
                overlap_len += 1
            else:
                print("A: not found!")
                break ## no circular found, go to next sequence
        else:
            outline2 = ">" + rec.id + " overlap between 5' and 3' are " + \
                    str(overlap_len) +"bp\n" + overlap_seq
            print(outline2, file=fh_out2)

            outline = ">" + rec.id + "\n" + seq[0:start_pos]
            print(outline, file=fh_out)

            outline3 = ">" + rec.id + "\n" + seq[300:start_pos]+seq[0:300]
            print(outline3, file=fh_out3)

            break

fh_out.close()

