"""
Support for "biological sequence" files.

:Author: Bob Harris (rsharris@bx.psu.edu)

See seq.py for more information
"""

import struct

from . import (
    fasta,
    nib,
    qdna,
)

# DNA reverse complement table

DNA_COMP = (
    "                                             -                  "
    " TVGH  CD  M KN   YSA BWXR       tvgh  cd  m kn   ysa bwxr      "
    "                                                                "
    "                                                                "
)


def reverse_complement(text):
    return text.translate(DNA_COMP)[::-1]


def seq_file(file, format=None, revcomp=False, name="", gap=None, contig=None):
    if format is None:
        format = infer_format(file)
    if (contig is not None) and (format not in ["fasta", None]):
        raise ValueError(f"Contigs are not supported for format {format}")
    if format == "fasta":
        return fasta.FastaFile(file, revcomp=revcomp, name=name, gap=gap, contig=contig)
    elif format == "nib":
        return nib.NibFile(file, revcomp=revcomp, name=name, gap=gap)
    elif format == "qdna":
        return qdna.QdnaFile(file, revcomp=revcomp, name=name, gap=gap)
    else:
        if format is None:
            format = ""
        else:
            format = " " + format
        raise ValueError(f"Unknown sequence format{format} in {file.name}")


def seq_reader(file, format=None, revcomp=False, name="", gap=None):
    if format is None:
        format = infer_format(file)
    if format == "fasta":
        return fasta.FastaReader(file, revcomp=revcomp, name=name, gap=gap)
    elif format == "nib":
        return nib.NibReader(file, revcomp=revcomp, name=name, gap=gap)
    elif format == "qdna":
        return qdna.QdnaReader(file, revcomp=revcomp, name=name, gap=gap)
    else:
        raise ValueError(f"Unknown sequence format {format}")


def seq_writer(outfile, format=None, name=""):
    if format == "fasta":
        return fasta.FastaWriter(outfile)
    elif format == "nib":
        return nib.NibWriter(outfile)
    elif format == "qdna":
        return qdna.QdnaWriter(outfile)
    else:
        raise ValueError(f"Unknown sequence format {format}")


def infer_format(file):
    format = None
    magic = struct.unpack(">L", file.read(4))[0]
    if (magic == nib.NIB_MAGIC_NUMBER) or (magic == nib.NIB_MAGIC_NUMBER_SWAP):
        format = "nib"
    elif (magic == qdna.qdnaMagic) or (magic == qdna.qdnaMagicSwap):
        format = "qdna"
    else:
        file.seek(0)
        if file.read(1) == b">":
            format = "fasta"
    file.seek(0)
    return format
