#!/usr/bin/env python
# Copyright (c) 2013-2019 Quan Xu <qxuchn@gmail.com>
#
# This module is free software. You can redistribute it and/or modify it under
# the terms of the MIT License, see the file COPYING included with this
# distribution.

import sys
import ast
import argparse
from ananse import commands, __version__
from genomepy import Genome


class NegateAction(argparse.Action):
    def __call__(self, parser, ns, values, option):
        setattr(ns, self.dest, "include" in option)


if __name__ == "__main__":
    description = """
    ananse v{0}
    """.format(
        __version__
    )

    epilog = """
    commands:
        enhancer    make normalized H3K27ac enahncer file
        binding     infer TF binding sites in enhancer peaks
        network     built network for each sample
        influence   infer key TFs between two samples

    type `ananse <command> -h` for more details
    """
    usage = "%(prog)s [-h] <subcommand> [options]"

    parser = argparse.ArgumentParser(
        usage=usage,
        description=description,
        epilog=epilog,
        formatter_class=argparse.RawDescriptionHelpFormatter,
    )
    subparsers = parser.add_subparsers()

    # binding.py
    p = subparsers.add_parser("binding", add_help=False)
    group = p.add_argument_group("required arguments")
    group.add_argument(
        "-r",
        "--enhancers",
        required=True,
        dest="fin_rpkm",
        help="BED file with RPKM on the 4th column",
        metavar="FILE",
    )
    group.add_argument(
        "-o",
        "--output",
        required=True,
        dest="outfile",
        help="Output file",
        metavar="FILE",
        default=None,
    )
    group = p.add_argument_group("optional arguments")
    group.add_argument(
        "-g", "--genome", dest="genome", help="Genome", metavar="GENOME", default="hg38"
    )
    group.add_argument(
        "-t", 
        "--etype", 
        dest="etype", 
        help="The input enhancer data, hg38H3K27ac, p300 or ATAC. By default is H3K27ac.",
        default="hg38H3K27ac"
    )
    group.add_argument(
        "-p",
        "--pfmfile",
        dest="pfmfile",
        help="PFM file with motifs",
        metavar="FILE",
        default=None,
    )
    group.add_argument(
        "-f",
        "--tffile",
        dest="tffile",
        help="TF file used in analysis",
        metavar="FILE",
        default=None,
    )
    group.add_argument(
        "-n", "--ncore", dest="ncore", help="Number of core used", type=int,
    )
    group.add_argument(
        "-h", "--help", action="help", help="show this help message and exit"
    )
    # p.add_argument(
    #     "-d",
    #     "--keep_detail",
    #     dest="detail",
    #     help="Keep detailed output files, by default they are removed",
    #     action="store_true",
    #     default=False,
    # )
    group.add_argument(
        "--include-notfs",
        "--exclude-notfs",
        default=False,
        help="Include or exclude noTFs from database. By default no tfs are exclude.",
        dest="include_notfs",
        action=NegateAction,
        nargs=0,
    )
    group.add_argument(
        "--unremove-curated",
       # "--remove-curated",
        default=True,
        help="Include or exclude noTFs from database. By default no tfs are exclude.",
        dest="rm_curated",
        action=NegateAction,
        nargs=0,
    )
    p.set_defaults(func=commands.binding)

    # network.py
    p = subparsers.add_parser("network", add_help=False)
    group = p.add_argument_group("required arguments")
    group.add_argument(
        "-b", "--binding", dest="binding", help="All TFs binding file", metavar="FILE",
    )
    group.add_argument(
        "-e",
        "--expression",
        dest="fin_expression",
        help="Expression scores",
        metavar="FILE",
        nargs="*",
    )
    group.add_argument(
        "-o",
        "--output",
        required=True,
        dest="outfile",
        help="Output file",
        metavar="FILE",
        default=None,
    )
    group = p.add_argument_group("optional arguments")
    group.add_argument(
        "-g", "--genome", dest="genome", help="Genome", metavar="NAME", default="hg38",
    )
    group.add_argument(
        "-a",
        "--annotation",
        dest="annotation",
        help="Gene annotation in BED12 format",
        metavar="BED",
    )
    group.add_argument(
        "-c",
        "--corrfiles",
        dest="corrfiles",
        help="Files with correlation",
        metavar="FILE",
        nargs="*",
    )
    group.add_argument(
        "-n", "--ncore", dest="ncore", help="Number of core used", type=int,
    )
    group.add_argument(
        "--include-promoter",
        "--exclude-promoter",
        default=False,
        help="Include or exclude promoter peaks (<= TSS +/- 2kb) in network inference. By default promoter peaks are excluded.",
        dest="include_promoter",
        action=NegateAction,
        nargs=0,
    )
    group.add_argument(
        "--include-enhancer",
        "--exclude-enhancer",
        default=True,
        help="Include or exclude enhancer peaks (> TSS +/- 2kb) in network inference. By default enhancer peaks are included.",
        dest="include_enhancer",
        action=NegateAction,
        nargs=0,
    )
    group.add_argument(
        "-h", "--help", action="help", help="show this help message and exit"
    )

    # p.add_argument(
    #     "-r",
    #     "--enhancers",
    #     required=True,
    #     dest="fin_rpkm",
    #     help="BED file with RPKM on the 4th column",
    #     metavar="FILE",
    # )
    # p.add_argument(
    #     "-f",
    #     "--filter_promoter",
    #     dest="fpomoter",
    #     help="Filter promoters, True or False, input should be either 'True' or 'False'.",
    #     metavar="NAME",
    #     type=ast.literal_eval,
    #     default=True,
    # )

    # This not used currently
    # group.add_argument(
    #     "-i",
    #     "--impute",
    #     dest="impute",
    #     help="Impute missing values",
    #     default=False,
    #     action="store_true",
    # )

    p.set_defaults(func=commands.network)

    # # network.py
    # p = subparsers.add_parser("network")
    # p.add_argument(
    #     "-f",
    #     "--interaction",
    #     dest="features",
    #     help="HDF5 file with features",
    #     metavar="FILE",
    #     default=None,
    #     required=True,
    # )
    # p.add_argument(
    #     "-o",
    #     "--outfile",
    #     required=True,
    #     dest="outfile",
    #     help="Output file",
    #     metavar="FILE",
    #     default=None,
    # )
    # p.add_argument(
    #     "-i",
    #     "--impute",
    #     dest="impute",
    #     help="Impute missing values",
    #     default=False,
    #     action="store_true",
    # )
    # p.set_defaults(func=commands.network)

    # influence.py
    p = subparsers.add_parser("influence", add_help=False)

    group = p.add_argument_group("required arguments")
    group.add_argument(
        "-t",
        "--target",
        dest="Gaf",
        help="network in second cell",
        metavar="FILE",
        default=None,
    )
    group.add_argument(
        "-d", "--degenes", dest="expression", help="DE genes file", metavar="FILE",
    )
    group.add_argument(
        "-o",
        "--outfile",
        required=True,
        dest="outfile",
        help="Output file",
        metavar="FILE",
        default=None,
    )
    group = p.add_argument_group("optional arguments")
    group.add_argument(
        "-s",
        "--source",
        dest="Gbf",
        help="network in first cell",
        metavar="FILE",
        default=None,
    )
    group.add_argument(
        "-i",
        "--edges",
        dest="edges",
        help="Number of top edges used",
        type=int,
        default=100000,
    )
    group.add_argument(
        "-e",
        "--expression",
        dest="fin_expression",
        help="Expression scores in first cell",
        metavar="FILE",
    )
    group.add_argument(
        "-p",
        "--plot",
        dest="plot",
        help="Create influence score plot.",
        action="store_true",
        default=False,
    )
    group.add_argument(
        "-n", "--ncore", dest="ncore", help="Number of core used", type=int,
    )
    group.add_argument(
        "-h", "--help", action="help", help="show this help message and exit"
    )
    p.set_defaults(func=commands.influence)

    # enhancer.py
    p = subparsers.add_parser("enhancer", add_help=False)
    group = p.add_argument_group("required arguments")
    group.add_argument(
        "-g", "--genome", dest="genome", help="Genome", metavar="NAME", default="hg38",
    )
    group.add_argument(
        "-t", "--etype", dest="etype", help="Enhancer type, hg38H3K27ac, p300, or ATAC", metavar="NAME", default="hg38H3K27ac",
    )
    group.add_argument(
        "-b", "--bam_input", dest="bam_input", help="The original H3K27ac ChIP-seq bam file, or the p300 ChIP-seq bam file", metavar="FILE",
    )
    group.add_argument(
        "-p", "--epeak", dest="epeak", help="The original H3K27ac ChIP-seq broadPeak, or the p300 ChIP-seq / ATAC-seq narrowPeak", metavar="FILE",
    ) 
    group.add_argument(
        "-o", "--bed_output", dest="bed_output", help="The normalized H3K27ac enahncer file", metavar="FILE",
    )
    group.add_argument(
        "-h", "--help", action="help", help="show this help message and exit"
    )
    p.set_defaults(func=commands.enhancer)

    if len(sys.argv) == 1:
        parser.print_help()
    else:
        if len(sys.argv) == 2:
            print(
                "\033[93mtype `ananse {} -h` for more details\033[0m\n".format(
                    sys.argv[-1]
                )
            )
        args = parser.parse_args()

        if hasattr(args, "genome"):
            if args.genome is not None:
                try:
                    Genome(args.genome)
                except Exception:
                    print(
                        "Genome not found. Have you installed your genome with genomepy?"
                    )
                    print("See https://github.com/simonvh/genomepy for details.")
                    print("Alternatively, you can specify a FASTA file.")
                    exit(1)

        args.func(args)
