# Path: mirtop/gff/classgff.py
# class feature:
#     """"Class with alignment information."""
# 
#     def __init__(self, line, sep="="):
#         # if isinstance(line, basestring) # str in python 3
#         if isinstance(line, dict):
#             line = self.create_line(line, sep)
#         self.line = line
#         self.attributes = {}
#         self.columns = {}
#         self.read_gff_line()
#         self.reserved_attributes = gff_versions.ATTRv['1.1']
# 
#     def guess_format(self):
#         return "=" if self.line.find("Name=") > -1 else " "
# 
#     def create_line(self, fields, sep):
#         """
#         Create GFF/GTF line from dictionary with fields
#         """
#         # TODO: need unit test. Check all exists.
#         fields["attrb"] = ("Read {seq_name}; UID {idseq}; Name {name};"
#                            "Parent {parent}; "
#                            "Variant {variant}; Cigar {cigar};"
#                            "Expression {counts}; "
#                            "Filter {filter}; Hits {hits};").format(**fields)
# 
#         line = ("{chrom}\t{database}\t{source}\t{start}\t{end}"
#                 "\t{score}\t{strand}\t.\t{attrb}").format(**fields)
#         return line
# 
#     def paste_columns(self, sep=None):
#         """
#         Create GFF/GTF line from read_gff_line
#         """
#         sep = self.guess_format()
#         attributes = "%s;" % "; ".join(
#             "%s%s%s" % (a, sep, self.attributes[a]) for a in self.attributes)
#         return "\t".join([self.columns['chrom'], self.columns['source'],
#                           self.columns['type'],
#                           self.columns['start'], self.columns['end'],
#                           self.columns['score'],
#                           self.columns['strand'], self.columns['ext'],
#                           attributes])
# 
#     def read_attributes(self, gff_attrb, sep=" "):
#         """
#         Read GFF/GTF attributes and return dictionary with fields
#         """
#         sep = self.guess_format()
#         gff_dict = OrderedDict()
#         for gff_item in gff_attrb.split(";"):
#             item_pair = gff_item.strip().split(sep)
#             if len(item_pair) > 1:
#                 gff_dict[item_pair[0].strip()] = item_pair[1].strip()
#         self.attributes = gff_dict
# 
#     def read_gff_line(self):
#         """
#         Read GFF/GTF line and return dictionary with fields
#         """
#         line = self.line
#         if line.startswith("#"):
#             return line
#         cols = line.strip().split("\t")
#         if len(cols) != 9:
#             raise ValueError("Line has less than 9 elements: %s" % line)
#         self.read_attributes(cols[8])
#         fields = {'chrom': cols[0],
#                   'source': cols[1],
#                   'type': cols[2],
#                   'start': cols[3],
#                   'end': cols[4],
#                   'score': cols[5],
#                   'strand': cols[6],
#                   'ext': cols[7]}
#         self.columns = fields
# 
# Path: mirtop/gff/header.py
# def read_version(fn):
#     """Extract mirGFF3 version"""
#     with open(fn) as inh:
#         for line in inh:
#             if line.find("VERSION") > -1:
#                 return line.split("VERSION")[1].strip()
#             if not line.startswith("#"):
#                 ValueError("Version not found in the header."
#                            "A valid file should have a line like this:"
#                            "## mirGFF3. VERSION X.X")
# 
# def get_gff_version():
#     return ("## mirGFF3. VERSION"
#             " %s\n" % version.current)
# 
# Path: mirtop/mirna/realign.py
# def make_id(seq):
#     """
#     Create a unique identifier for the sequence from the nucleotides,
#     replacing 5 nts for a unique sequence.
# 
#     It uses the code from *mirtop.mirna.keys()*.
# 
#     Inspired by MINTplate: https://cm.jefferson.edu/MINTbase
#     https://github.com/TJU-CMC-Org/MINTmap/tree/master/MINTplates
# 
#     Args:
#         *seq(str)*: nucleotides sequences.
# 
#     Returns:
#         *idName(str)*: unique identifier for the sequence.
#     """
#     try:
#         idu = convert(seq, True, 'iso')
#     except KeyError as error:
#         logger.error("Sequence is not valid " + seq)
#         raise
# 
#     # If you wanted to add "iso-" into the license plate as the prefix
#     # idu = convert(seq, True, "iso")
#     return idu


import sys
import os
import mirtop.libs.logger as mylog
from mirtop.gff.classgff import feature
from mirtop.gff.header import read_version, get_gff_version
from mirtop.mirna.keys import *
from mirtop.mirna.realign import make_id
    Update previous GFF3 versions.

    Args:
        *args (namedtupled)*: arguments parsed from command line with
            *mirtop.libs.parse.add_subparser_update()*.

    Returns:
        *(out_file)*: most updated GFF3 file.
    """    
    for fn in args.files:
        out_fn = os.path.join(args.out, os.path.basename(fn))
        update_file(fn, out_fn)


def read_uid_10(idu):
    seq = ""
    for i in idu:
        if i == "1" or i == "2":
            return seq[:-int(i)]
        else:
            if i not in CODE2NT:
                logger.error("UID is not valid (%s)" % idu)
                return False
            seq += CODE2NT[i]
    return seq


def to10to11(gff_line):
    gff_line = gff_line.replace("_snp", "_snv")
    gff_line = gff_line.replace("_add", "_add3p")

# Path: mirtop/gff/classgff.py
# class feature:
#     """"Class with alignment information."""
# 
#     def __init__(self, line, sep="="):
#         # if isinstance(line, basestring) # str in python 3
#         if isinstance(line, dict):
#             line = self.create_line(line, sep)
#         self.line = line
#         self.attributes = {}
#         self.columns = {}
#         self.read_gff_line()
#         self.reserved_attributes = gff_versions.ATTRv['1.1']
# 
#     def guess_format(self):
#         return "=" if self.line.find("Name=") > -1 else " "
# 
#     def create_line(self, fields, sep):
#         """
#         Create GFF/GTF line from dictionary with fields
#         """
#         # TODO: need unit test. Check all exists.
#         fields["attrb"] = ("Read {seq_name}; UID {idseq}; Name {name};"
#                            "Parent {parent}; "
#                            "Variant {variant}; Cigar {cigar};"
#                            "Expression {counts}; "
#                            "Filter {filter}; Hits {hits};").format(**fields)
# 
#         line = ("{chrom}\t{database}\t{source}\t{start}\t{end}"
#                 "\t{score}\t{strand}\t.\t{attrb}").format(**fields)
#         return line
# 
#     def paste_columns(self, sep=None):
#         """
#         Create GFF/GTF line from read_gff_line
#         """
#         sep = self.guess_format()
#         attributes = "%s;" % "; ".join(
#             "%s%s%s" % (a, sep, self.attributes[a]) for a in self.attributes)
#         return "\t".join([self.columns['chrom'], self.columns['source'],
#                           self.columns['type'],
#                           self.columns['start'], self.columns['end'],
#                           self.columns['score'],
#                           self.columns['strand'], self.columns['ext'],
#                           attributes])
# 
#     def read_attributes(self, gff_attrb, sep=" "):
#         """
#         Read GFF/GTF attributes and return dictionary with fields
#         """
#         sep = self.guess_format()
#         gff_dict = OrderedDict()
#         for gff_item in gff_attrb.split(";"):
#             item_pair = gff_item.strip().split(sep)
#             if len(item_pair) > 1:
#                 gff_dict[item_pair[0].strip()] = item_pair[1].strip()
#         self.attributes = gff_dict
# 
#     def read_gff_line(self):
#         """
#         Read GFF/GTF line and return dictionary with fields
#         """
#         line = self.line
#         if line.startswith("#"):
#             return line
#         cols = line.strip().split("\t")
#         if len(cols) != 9:
#             raise ValueError("Line has less than 9 elements: %s" % line)
#         self.read_attributes(cols[8])
#         fields = {'chrom': cols[0],
#                   'source': cols[1],
#                   'type': cols[2],
#                   'start': cols[3],
#                   'end': cols[4],
#                   'score': cols[5],
#                   'strand': cols[6],
#                   'ext': cols[7]}
#         self.columns = fields
# 
# Path: mirtop/gff/header.py
# def read_version(fn):
#     """Extract mirGFF3 version"""
#     with open(fn) as inh:
#         for line in inh:
#             if line.find("VERSION") > -1:
#                 return line.split("VERSION")[1].strip()
#             if not line.startswith("#"):
#                 ValueError("Version not found in the header."
#                            "A valid file should have a line like this:"
#                            "## mirGFF3. VERSION X.X")
# 
# def get_gff_version():
#     return ("## mirGFF3. VERSION"
#             " %s\n" % version.current)
# 
# Path: mirtop/mirna/realign.py
# def make_id(seq):
#     """
#     Create a unique identifier for the sequence from the nucleotides,
#     replacing 5 nts for a unique sequence.
# 
#     It uses the code from *mirtop.mirna.keys()*.
# 
#     Inspired by MINTplate: https://cm.jefferson.edu/MINTbase
#     https://github.com/TJU-CMC-Org/MINTmap/tree/master/MINTplates
# 
#     Args:
#         *seq(str)*: nucleotides sequences.
# 
#     Returns:
#         *idName(str)*: unique identifier for the sequence.
#     """
#     try:
#         idu = convert(seq, True, 'iso')
#     except KeyError as error:
#         logger.error("Sequence is not valid " + seq)
#         raise
# 
#     # If you wanted to add "iso-" into the license plate as the prefix
#     # idu = convert(seq, True, "iso")
#     return idu


# Path: mirtop/gff/update.py
import sys
import os
import mirtop.libs.logger as mylog
from mirtop.gff.classgff import feature
from mirtop.gff.header import read_version, get_gff_version
from mirtop.mirna.keys import *
from mirtop.mirna.realign import make_id

    Update previous GFF3 versions.

    Args:
        *args (namedtupled)*: arguments parsed from command line with
            *mirtop.libs.parse.add_subparser_update()*.

    Returns:
        *(out_file)*: most updated GFF3 file.
    """    
    for fn in args.files:
        out_fn = os.path.join(args.out, os.path.basename(fn))
        update_file(fn, out_fn)


def read_uid_10(idu):
    seq = ""
    for i in idu:
        if i == "1" or i == "2":
            return seq[:-int(i)]
        else:
            if i not in CODE2NT:
                logger.error("UID is not valid (%s)" % idu)
                return False
            seq += CODE2NT[i]
    return seq


def to10to11(gff_line):
    gff_line = gff_line.replace("_snp", "_snv")
    gff_line = gff_line.replace("_add", "_add3p")

    features = feature(gff_line)