"""Functions for JSON-based serialization and deserialization of Fama objects"""
import os
import json
from fama.project.sample import Sample
from fama.diamond_parser.diamond_hit import DiamondHit
from fama.diamond_parser.diamond_hit_list import DiamondHitList
from fama.sequences.annotated_read import AnnotatedRead
from fama.gene_assembler.contig import Contig
from fama.gene_assembler.gene import Gene
from fama.gene_assembler.gene_assembly import GeneAssembly


def decode_reads(obj):
    """Custom JSON decoder for AnnotatedRead object

    Args:
        obj (obj): AnnotatedRead object to decode
    """
    if '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_sample(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): Sample object to decode
    """
    if '__Sample__' in obj:
        sample = Sample()
        sample.__dict__.update(obj['__Sample__'])
        return sample
    elif '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_assembly(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): GeneAssembly object to decode
    """
    if '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    elif '__Contig__' in obj:
        contig = Contig()
        contig.__dict__.update(obj['__Contig__'])
        return contig
    elif '__Gene__' in obj:
        gene = Gene()
        gene.__dict__.update(obj['__Gene__'])
        return gene
    elif '__GeneAssembly__' in obj:
        gene_assembly = GeneAssembly()
        gene_assembly.__dict__.update(obj['__GeneAssembly__'])
        return gene_assembly
    return obj


def import_annotated_reads(infile):
    """Imports annotated reads from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (dict[str, :obj:AnnotatedRead]): key is read identifier,
            value is annotated read
    """
    deserialized = None
    try:
        with open(infile, 'r') as file_handle:
            deserialized = json.load(file_handle, object_hook=decode_reads)
    except FileNotFoundError:
        deserialized = {}
    return deserialized


def import_sample(infile):
    """Imports sample from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:Sample): sample object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_sample)
    return deserialized


def import_gene_assembly(infile):
    """Imports gene assembly from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:GeneAssembly): gene assembly object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_assembly)
    return deserialized


def export_annotated_reads(parser):
    """Exports annotated reads in JSON format

    Args:
        parser (:obj:DiamondParser): parser with annotated reads
    """
    outfile = os.path.join(
        parser.options.get_project_dir(parser.sample.sample_id),
        parser.sample.sample_id + '_' + parser.end + '_' + parser.options.reads_json_name
    )
    # print pretty JSON: print(json.dumps(parser.reads,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        json.dump(parser.reads, out, cls=CustomEncoder)


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id + '_sample.json')
    # print pretty JSON: print(json.dumps(parser.reads,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        # out.write(json.dumps(sample, indent=4, cls=CustomEncoder))
        json.dump(sample, out, cls=CustomEncoder)


def export_gene_assembly(assembly, outfile):
    """Saves GeneAssembly object as JSON file

    Args:
        assembly (:obj:GeneAssembly): gene assembly
        outfile (str): output file name
    """
    # print pretty JSON: print(json.dumps(assembly,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        json.dump(assembly, out, indent=4, cls=CustomEncoder)


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""
    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}

6e3daa7fef9f923c5eb9eb3c04418990413030d3
<mask token>


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id +
        '_sample.json')
    with open(outfile, 'w') as out:
        json.dump(sample, out, cls=CustomEncoder)


<mask token>


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""

    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}

<mask token>


def import_sample(infile):
    """Imports sample from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:Sample): sample object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_sample)
    return deserialized


def import_gene_assembly(infile):
    """Imports gene assembly from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:GeneAssembly): gene assembly object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_assembly)
    return deserialized


<mask token>


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id +
        '_sample.json')
    with open(outfile, 'w') as out:
        json.dump(sample, out, cls=CustomEncoder)


def export_gene_assembly(assembly, outfile):
    """Saves GeneAssembly object as JSON file

    Args:
        assembly (:obj:GeneAssembly): gene assembly
        outfile (str): output file name
    """
    with open(outfile, 'w') as out:
        json.dump(assembly, out, indent=4, cls=CustomEncoder)


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""

    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}

<mask token>


def decode_reads(obj):
    """Custom JSON decoder for AnnotatedRead object

    Args:
        obj (obj): AnnotatedRead object to decode
    """
    if '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_sample(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): Sample object to decode
    """
    if '__Sample__' in obj:
        sample = Sample()
        sample.__dict__.update(obj['__Sample__'])
        return sample
    elif '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_assembly(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): GeneAssembly object to decode
    """
    if '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    elif '__Contig__' in obj:
        contig = Contig()
        contig.__dict__.update(obj['__Contig__'])
        return contig
    elif '__Gene__' in obj:
        gene = Gene()
        gene.__dict__.update(obj['__Gene__'])
        return gene
    elif '__GeneAssembly__' in obj:
        gene_assembly = GeneAssembly()
        gene_assembly.__dict__.update(obj['__GeneAssembly__'])
        return gene_assembly
    return obj


def import_annotated_reads(infile):
    """Imports annotated reads from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (dict[str, :obj:AnnotatedRead]): key is read identifier,
            value is annotated read
    """
    deserialized = None
    try:
        with open(infile, 'r') as file_handle:
            deserialized = json.load(file_handle, object_hook=decode_reads)
    except FileNotFoundError:
        deserialized = {}
    return deserialized


def import_sample(infile):
    """Imports sample from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:Sample): sample object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_sample)
    return deserialized


def import_gene_assembly(infile):
    """Imports gene assembly from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:GeneAssembly): gene assembly object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_assembly)
    return deserialized


<mask token>


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id +
        '_sample.json')
    with open(outfile, 'w') as out:
        json.dump(sample, out, cls=CustomEncoder)


def export_gene_assembly(assembly, outfile):
    """Saves GeneAssembly object as JSON file

    Args:
        assembly (:obj:GeneAssembly): gene assembly
        outfile (str): output file name
    """
    with open(outfile, 'w') as out:
        json.dump(assembly, out, indent=4, cls=CustomEncoder)


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""

    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}

<mask token>
import os
import json
from fama.project.sample import Sample
from fama.diamond_parser.diamond_hit import DiamondHit
from fama.diamond_parser.diamond_hit_list import DiamondHitList
from fama.sequences.annotated_read import AnnotatedRead
from fama.gene_assembler.contig import Contig
from fama.gene_assembler.gene import Gene
from fama.gene_assembler.gene_assembly import GeneAssembly


def decode_reads(obj):
    """Custom JSON decoder for AnnotatedRead object

    Args:
        obj (obj): AnnotatedRead object to decode
    """
    if '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_sample(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): Sample object to decode
    """
    if '__Sample__' in obj:
        sample = Sample()
        sample.__dict__.update(obj['__Sample__'])
        return sample
    elif '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_assembly(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): GeneAssembly object to decode
    """
    if '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    elif '__Contig__' in obj:
        contig = Contig()
        contig.__dict__.update(obj['__Contig__'])
        return contig
    elif '__Gene__' in obj:
        gene = Gene()
        gene.__dict__.update(obj['__Gene__'])
        return gene
    elif '__GeneAssembly__' in obj:
        gene_assembly = GeneAssembly()
        gene_assembly.__dict__.update(obj['__GeneAssembly__'])
        return gene_assembly
    return obj


def import_annotated_reads(infile):
    """Imports annotated reads from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (dict[str, :obj:AnnotatedRead]): key is read identifier,
            value is annotated read
    """
    deserialized = None
    try:
        with open(infile, 'r') as file_handle:
            deserialized = json.load(file_handle, object_hook=decode_reads)
    except FileNotFoundError:
        deserialized = {}
    return deserialized


def import_sample(infile):
    """Imports sample from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:Sample): sample object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_sample)
    return deserialized


def import_gene_assembly(infile):
    """Imports gene assembly from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:GeneAssembly): gene assembly object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_assembly)
    return deserialized


def export_annotated_reads(parser):
    """Exports annotated reads in JSON format

    Args:
        parser (:obj:DiamondParser): parser with annotated reads
    """
    outfile = os.path.join(parser.options.get_project_dir(parser.sample.
        sample_id), parser.sample.sample_id + '_' + parser.end + '_' +
        parser.options.reads_json_name)
    with open(outfile, 'w') as out:
        json.dump(parser.reads, out, cls=CustomEncoder)


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id +
        '_sample.json')
    with open(outfile, 'w') as out:
        json.dump(sample, out, cls=CustomEncoder)


def export_gene_assembly(assembly, outfile):
    """Saves GeneAssembly object as JSON file

    Args:
        assembly (:obj:GeneAssembly): gene assembly
        outfile (str): output file name
    """
    with open(outfile, 'w') as out:
        json.dump(assembly, out, indent=4, cls=CustomEncoder)


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""

    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}

"""Functions for JSON-based serialization and deserialization of Fama objects"""
import os
import json
from fama.project.sample import Sample
from fama.diamond_parser.diamond_hit import DiamondHit
from fama.diamond_parser.diamond_hit_list import DiamondHitList
from fama.sequences.annotated_read import AnnotatedRead
from fama.gene_assembler.contig import Contig
from fama.gene_assembler.gene import Gene
from fama.gene_assembler.gene_assembly import GeneAssembly


def decode_reads(obj):
    """Custom JSON decoder for AnnotatedRead object

    Args:
        obj (obj): AnnotatedRead object to decode
    """
    if '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_sample(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): Sample object to decode
    """
    if '__Sample__' in obj:
        sample = Sample()
        sample.__dict__.update(obj['__Sample__'])
        return sample
    elif '__AnnotatedRead__' in obj:
        annotated_read = AnnotatedRead()
        annotated_read.__dict__.update(obj['__AnnotatedRead__'])
        return annotated_read
    elif '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    return obj


def decode_assembly(obj):
    """Custom JSON decoder for Sample object

    Args:
        obj (obj): GeneAssembly object to decode
    """
    if '__DiamondHitList__' in obj:
        diamond_hit_list = DiamondHitList()
        diamond_hit_list.__dict__.update(obj['__DiamondHitList__'])
        return diamond_hit_list
    elif '__DiamondHit__' in obj:
        diamond_hit = DiamondHit()
        diamond_hit.__dict__.update(obj['__DiamondHit__'])
        return diamond_hit
    elif '__Contig__' in obj:
        contig = Contig()
        contig.__dict__.update(obj['__Contig__'])
        return contig
    elif '__Gene__' in obj:
        gene = Gene()
        gene.__dict__.update(obj['__Gene__'])
        return gene
    elif '__GeneAssembly__' in obj:
        gene_assembly = GeneAssembly()
        gene_assembly.__dict__.update(obj['__GeneAssembly__'])
        return gene_assembly
    return obj


def import_annotated_reads(infile):
    """Imports annotated reads from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (dict[str, :obj:AnnotatedRead]): key is read identifier,
            value is annotated read
    """
    deserialized = None
    try:
        with open(infile, 'r') as file_handle:
            deserialized = json.load(file_handle, object_hook=decode_reads)
    except FileNotFoundError:
        deserialized = {}
    return deserialized


def import_sample(infile):
    """Imports sample from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:Sample): sample object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_sample)
    return deserialized


def import_gene_assembly(infile):
    """Imports gene assembly from JSON file

    Args:
        infile (str): JSON file name

    Returns:
        deserialized (:obj:GeneAssembly): gene assembly object
    """
    deserialized = None
    with open(infile, 'r') as file_handle:
        deserialized = json.load(file_handle, object_hook=decode_assembly)
    return deserialized


def export_annotated_reads(parser):
    """Exports annotated reads in JSON format

    Args:
        parser (:obj:DiamondParser): parser with annotated reads
    """
    outfile = os.path.join(
        parser.options.get_project_dir(parser.sample.sample_id),
        parser.sample.sample_id + '_' + parser.end + '_' + parser.options.reads_json_name
    )
    # print pretty JSON: print(json.dumps(parser.reads,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        json.dump(parser.reads, out, cls=CustomEncoder)


def export_sample(sample):
    """Exports sample in JSON format

    Args:
        sample (:obj:Sample): sample object
    """
    outfile = os.path.join(sample.work_directory, sample.sample_id + '_sample.json')
    # print pretty JSON: print(json.dumps(parser.reads,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        # out.write(json.dumps(sample, indent=4, cls=CustomEncoder))
        json.dump(sample, out, cls=CustomEncoder)


def export_gene_assembly(assembly, outfile):
    """Saves GeneAssembly object as JSON file

    Args:
        assembly (:obj:GeneAssembly): gene assembly
        outfile (str): output file name
    """
    # print pretty JSON: print(json.dumps(assembly,indent=4, cls=CustomEncoder))
    with open(outfile, 'w') as out:
        json.dump(assembly, out, indent=4, cls=CustomEncoder)


class CustomEncoder(json.JSONEncoder):
    """Custom JSON encoder class"""
    def default(self, obj):
        """Returns encoded object as JSON-formatted string

        Args:
            obj (object): instance to encode
        """
        return {'__{}__'.format(obj.__class__.__name__): obj.__dict__}
