# Path: augur/utils.py
# def read_metadata(fname, query=None, as_data_frame=False):
#     return MetadataFile(fname, query, as_data_frame).read()
# 
# def read_node_data(fnames, tree=None):
#     return NodeDataReader(fnames, tree).read()
# 
# def write_json(data, file_name, indent=(None if os.environ.get("AUGUR_MINIFY_JSON") else 2), include_version=True):
#     """
#     Write ``data`` as JSON to the given ``file_name``, creating parent directories
#     if necessary. The augur version is included as a top-level key "augur_version".
# 
#     Parameters
#     ----------
#     data : dict
#         data to write out to JSON
#     file_name : str
#         file name to write to
#     indent : int or None, optional
#         JSON indentation level. Default is `None` if the environment variable `AUGUR_MINIFY_JSON`
#         is truthy, else 1
#     include_version : bool, optional
#         Include the augur version. Default: `True`.
# 
#     Raises
#     ------
#     OSError
#     """
#     #in case parent folder does not exist yet
#     parent_directory = os.path.dirname(file_name)
#     if parent_directory and not os.path.exists(parent_directory):
#         try:
#             os.makedirs(parent_directory)
#         except OSError: #Guard against race condition
#             if not os.path.isdir(parent_directory):
#                 raise
# 
#     if include_version:
#         data["generated_by"] = {"program": "augur", "version": get_augur_version()}
# 
#     with open(file_name, 'w', encoding='utf-8') as handle:
#         json.dump(data, handle, indent=indent, sort_keys=True)
# 
# def read_config(fname):
#     if not (fname and os.path.isfile(fname)):
#         print("ERROR: config file %s not found."%fname)
#         return defaultdict(dict)
# 
#     try:
#         with open(fname, 'rb') as ifile:
#             config = json.load(ifile)
#     except json.decoder.JSONDecodeError as err:
#         print("FATAL ERROR:")
#         print("\tCouldn't parse the JSON file {}".format(fname))
#         print("\tError message: '{}'".format(err.msg))
#         print("\tLine number: '{}'".format(err.lineno))
#         print("\tColumn number: '{}'".format(err.colno))
#         print("\tYou must correct this file in order to proceed.")
#         sys.exit(2)
# 
#     return config
# 
# def read_lat_longs(overrides=None, use_defaults=True):
#     coordinates = {}
#     # TODO: make parsing of tsv files more robust while allow for whitespace delimiting for backwards compatibility
#     def add_line_to_coordinates(line):
#         if line.startswith('#') or line.strip() == "":
#             return
#         fields = line.strip().split() if not '\t' in line else line.strip().split('\t')
#         if len(fields) == 4:
#             geo_field, loc = fields[0].lower(), fields[1].lower()
#             lat, long = float(fields[2]), float(fields[3])
#             coordinates[(geo_field, loc)] = {
#                 "latitude": lat,
#                 "longitude": long
#             }
#         else:
#             print("WARNING: geo-coordinate file contains invalid line. Please make sure not to mix tabs and spaces as delimiters (use only tabs):",line)
#     if use_defaults:
#         with resource_stream(__package__, "data/lat_longs.tsv") as stream:
#             with TextIOWrapper(stream, "utf-8") as defaults:
#                 for line in defaults:
#                     add_line_to_coordinates(line)
#     if overrides:
#         if os.path.isfile(overrides):
#             with open(overrides, encoding='utf-8') as ifile:
#                 for line in ifile:
#                     add_line_to_coordinates(line)
#         else:
#             print("WARNING: input lat/long file %s not found." % overrides)
#     return coordinates
# 
# def read_colors(overrides=None, use_defaults=True):
#     return ColorParser(mapping_filename=overrides, use_defaults=use_defaults).mapping


import os, sys
import re
import time
import numpy as np
from Bio import Phylo
from argparse import SUPPRESS
from collections import defaultdict
from .utils import read_metadata, read_node_data, write_json, read_config, read_lat_longs, read_colors
        from Bio import SeqIO
    core.add_argument('--metadata', required=True, metavar="FILE", help="sequence metadata, as CSV or TSV")
    core.add_argument('--node-data', required=True, nargs='+', help="JSON files with meta data for each node")
    core.add_argument('--output-tree', help="JSON file name that is passed on to auspice (e.g., zika_tree.json).")
    core.add_argument('--output-meta', help="JSON file name that is passed on to auspice (e.g., zika_meta.json).")
    core.add_argument('--auspice-config', help="file with auspice configuration")
    return core


def add_option_args(parser):
    options = parser.add_argument_group("OPTIONS")
    options.add_argument('--colors', metavar="FILE", help="Custom color definitions, one per line in the format `TRAIT_TYPE\\tTRAIT_VALUE\\tHEX_CODE`")
    options.add_argument('--lat-longs', help="file latitudes and longitudes, overrides built in mappings")
    options.add_argument('--tree-name', default=False, help="Tree name (needed for tangle tree functionality)")
    options.add_argument('--minify-json', action="store_true", help="export JSONs without indentation or line returns")
    options.add_argument('--output-sequence', help="JSON file name that is passed on to auspice (e.g., zika_seq.json).")
    options.add_argument('--reference', required=False, help="reference sequence for export to browser, only vcf")
    options.add_argument('--reference-translations', required=False, help="reference translations for export to browser, only vcf")
    return options


def register_arguments_v1(subparsers):
    # V1 sub-command
    v1 = subparsers.add_parser('v1', help="Export version 1 JSON schema (separate meta and tree JSONs)")
    v1_core = add_core_args(v1)
    v1_options = add_option_args(v1)
    v1.add_argument("--v1", help=SUPPRESS, default=True)


def run_v1(args):
    T = Phylo.read(args.tree, 'newick')

# Path: augur/utils.py
# def read_metadata(fname, query=None, as_data_frame=False):
#     return MetadataFile(fname, query, as_data_frame).read()
# 
# def read_node_data(fnames, tree=None):
#     return NodeDataReader(fnames, tree).read()
# 
# def write_json(data, file_name, indent=(None if os.environ.get("AUGUR_MINIFY_JSON") else 2), include_version=True):
#     """
#     Write ``data`` as JSON to the given ``file_name``, creating parent directories
#     if necessary. The augur version is included as a top-level key "augur_version".
# 
#     Parameters
#     ----------
#     data : dict
#         data to write out to JSON
#     file_name : str
#         file name to write to
#     indent : int or None, optional
#         JSON indentation level. Default is `None` if the environment variable `AUGUR_MINIFY_JSON`
#         is truthy, else 1
#     include_version : bool, optional
#         Include the augur version. Default: `True`.
# 
#     Raises
#     ------
#     OSError
#     """
#     #in case parent folder does not exist yet
#     parent_directory = os.path.dirname(file_name)
#     if parent_directory and not os.path.exists(parent_directory):
#         try:
#             os.makedirs(parent_directory)
#         except OSError: #Guard against race condition
#             if not os.path.isdir(parent_directory):
#                 raise
# 
#     if include_version:
#         data["generated_by"] = {"program": "augur", "version": get_augur_version()}
# 
#     with open(file_name, 'w', encoding='utf-8') as handle:
#         json.dump(data, handle, indent=indent, sort_keys=True)
# 
# def read_config(fname):
#     if not (fname and os.path.isfile(fname)):
#         print("ERROR: config file %s not found."%fname)
#         return defaultdict(dict)
# 
#     try:
#         with open(fname, 'rb') as ifile:
#             config = json.load(ifile)
#     except json.decoder.JSONDecodeError as err:
#         print("FATAL ERROR:")
#         print("\tCouldn't parse the JSON file {}".format(fname))
#         print("\tError message: '{}'".format(err.msg))
#         print("\tLine number: '{}'".format(err.lineno))
#         print("\tColumn number: '{}'".format(err.colno))
#         print("\tYou must correct this file in order to proceed.")
#         sys.exit(2)
# 
#     return config
# 
# def read_lat_longs(overrides=None, use_defaults=True):
#     coordinates = {}
#     # TODO: make parsing of tsv files more robust while allow for whitespace delimiting for backwards compatibility
#     def add_line_to_coordinates(line):
#         if line.startswith('#') or line.strip() == "":
#             return
#         fields = line.strip().split() if not '\t' in line else line.strip().split('\t')
#         if len(fields) == 4:
#             geo_field, loc = fields[0].lower(), fields[1].lower()
#             lat, long = float(fields[2]), float(fields[3])
#             coordinates[(geo_field, loc)] = {
#                 "latitude": lat,
#                 "longitude": long
#             }
#         else:
#             print("WARNING: geo-coordinate file contains invalid line. Please make sure not to mix tabs and spaces as delimiters (use only tabs):",line)
#     if use_defaults:
#         with resource_stream(__package__, "data/lat_longs.tsv") as stream:
#             with TextIOWrapper(stream, "utf-8") as defaults:
#                 for line in defaults:
#                     add_line_to_coordinates(line)
#     if overrides:
#         if os.path.isfile(overrides):
#             with open(overrides, encoding='utf-8') as ifile:
#                 for line in ifile:
#                     add_line_to_coordinates(line)
#         else:
#             print("WARNING: input lat/long file %s not found." % overrides)
#     return coordinates
# 
# def read_colors(overrides=None, use_defaults=True):
#     return ColorParser(mapping_filename=overrides, use_defaults=use_defaults).mapping


# Path: augur/export_v1.py
import os, sys
import re
import time
import numpy as np
from Bio import Phylo
from argparse import SUPPRESS
from collections import defaultdict
from .utils import read_metadata, read_node_data, write_json, read_config, read_lat_longs, read_colors
        from Bio import SeqIO

    core.add_argument('--metadata', required=True, metavar="FILE", help="sequence metadata, as CSV or TSV")
    core.add_argument('--node-data', required=True, nargs='+', help="JSON files with meta data for each node")
    core.add_argument('--output-tree', help="JSON file name that is passed on to auspice (e.g., zika_tree.json).")
    core.add_argument('--output-meta', help="JSON file name that is passed on to auspice (e.g., zika_meta.json).")
    core.add_argument('--auspice-config', help="file with auspice configuration")
    return core


def add_option_args(parser):
    options = parser.add_argument_group("OPTIONS")
    options.add_argument('--colors', metavar="FILE", help="Custom color definitions, one per line in the format `TRAIT_TYPE\\tTRAIT_VALUE\\tHEX_CODE`")
    options.add_argument('--lat-longs', help="file latitudes and longitudes, overrides built in mappings")
    options.add_argument('--tree-name', default=False, help="Tree name (needed for tangle tree functionality)")
    options.add_argument('--minify-json', action="store_true", help="export JSONs without indentation or line returns")
    options.add_argument('--output-sequence', help="JSON file name that is passed on to auspice (e.g., zika_seq.json).")
    options.add_argument('--reference', required=False, help="reference sequence for export to browser, only vcf")
    options.add_argument('--reference-translations', required=False, help="reference translations for export to browser, only vcf")
    return options


def register_arguments_v1(subparsers):
    # V1 sub-command
    v1 = subparsers.add_parser('v1', help="Export version 1 JSON schema (separate meta and tree JSONs)")
    v1_core = add_core_args(v1)
    v1_options = add_option_args(v1)
    v1.add_argument("--v1", help=SUPPRESS, default=True)


def run_v1(args):
    T = Phylo.read(args.tree, 'newick')

    node_data = read_node_data(args.node_data) # args.node_data is an array of multiple files (or a single file)