"""MAmotif main script for running from the command line."""
import os
import sys
import argparse
import logging
from manorm import workflow as manorm_workflow
from motifscan.workflow import motifscan_run
from mamotif import __version__
from mamotif import workflow as mamotif_workflow

def argparser_config():
    """Configure the arguments parser.
    """
    description = """MAmotif -- An integrative toolkit for searching cell type-specific co-factors associated with differential binding."""
    parser = argparse.ArgumentParser(description=description, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument('--version', action='version', version="%(prog)s {}".format(__version__))
    group_input = parser.add_argument_group("MAnorm Input File Arguments")
    group_input.add_argument("--p1", dest="peaks_file1", type=str, required=True,
                             help="Path of peaks file of sample 1. BED and MACS format are currently supported."
                                  "Please refer to documents for details.")
    group_input.add_argument("--p2", dest="peaks_file2", type=str, required=True,
                             help="Path of peaks file of sample 2.")
    group_input.add_argument("--r1", dest="reads_file1", type=str, required=True,
                             help="Path of reads file of sample 1. BED format are currently supported.")
    group_input.add_argument("--r2", dest="reads_file2", type=str, required=True,
                             help="Path of reads file of sample 2.")
    group_input.add_argument("--s1", dest="shift_size1", type=int, default=100,
                             help="Reads shiftsize of sample 1. This value is used to shift reads towards 3' direction"
                                  "to account for the actual binding site. Set as half of the fragment length.")
    group_input.add_argument("--s2", dest="shift_size2", type=int, default=100,
                             help="Reads shiftsize of sample 2.")

    group_input = parser.add_argument_group("Motifscan Input File Arguments")
    group_input.add_argument('-m', '--motif', dest='motif', type=str, required=True,
                             help="Required pre-compiled motif file, which is generated by 'motifcompile'.")
    group_input.add_argument('-g', '--genome', dest='genome', type=str, required=True,
                             help="Required genome directory, which contains genome sequence and chromosome length. "
                                  "You can run 'genomecompile' to generate the directory.")
    group_input.add_argument('-a', '--annotation', dest='gene', type=str,
                             help="Gene annotation file, which is used to generate random controls when performing "
                                  "enrichment analysis. Sequence features on promoters are very different from those "
                                  "on whole genome. We will pick up random control regions with similar genomic "
                                  "locations for each input region instead of the whole genome.")

    group_model = parser.add_argument_group("Normalization Model Arguments")
    group_model.add_argument("-w", dest="width", type=int, default=1000,
                             help="Half width of the window size when calculating read densities. Each window with "
                                  "length of 2*width is centered at peak summit or midpoint. This value should match "
                                  "the typical length of peaks, thus we recommend 1000 for sharp histone marks like "
                                  "H3K4me3 and H3K9/27ac, or 500 for transcription factors or DNase-Seq.")
    group_model.add_argument("-d", dest="distance_cutoff", type=int,
                             help="Summit to summit distance cutoff for common peaks. Default=width/2. Only peaks "
                                  "with summit distance less than than this value are considered as real common peaks "
                                  "of two samples.")

    group_advanced = parser.add_argument_group("Advanced arguments")
    group_advanced.add_argument("-n", dest="random_times", type=int, default=5,
                                help="Times of permutation to test the enrichment of peak overlap between two samples.")
    group_advanced.add_argument("-v", dest="overlap_dependent", action="store_true", default=False,
                                help="With this option on, MAnorm will pick out biased/unbiased peaks in an "
                                     "overlap-dependent manner. Biased peaks are only chosen from unique peaks, "
                                     "and unbiased peaks are only chosen from common peaks.")
    group_advanced.add_argument("-p", dest="p_cutoff", type=float, default=0.01,
                                help="P-value cutoff to define biased (sample 1/2-specific) peaks.")
    group_advanced.add_argument("--m_cutoff", dest="m_cutoff", type=float, default=1.0,
                                help="M-value cutoff to distinguish biased peaks from unbiased peaks. Peaks with "
                                     "M-value>=M_cutoff and P-value<=P_cutoff as defined as sample1-biased(specific) "
                                     "peaks, while peaks with M-value<=-1*M_cutoff and P-value<=P_cutoff are defined "
                                     "as sample2-biased peaks.")

    group_advanced.add_argument('-l', '--motif_list', dest='motif_list', type=str,
                                help="Motif list file. If specified, the program will only perform MotifScan on given "
                                     "motifs in this list.")
    group_advanced.add_argument('-e', '--no_enrichment', dest='enrichment_flag', action='store_false', default=True,
                                help="If set, MotifScan will neither generate random control regions nor perform "
                                     "enrichment analysis.")
    # group_advanced.add_argument('-c', '--control', dest='control_file', type=str,
    #                            help="User specified control regions.")
    # group_advanced.add_argument('--cformat', dest='control_format', type=str, default="bed5col", choices=PEAK_FORMAT,
    #                            help="Format of control regions (same as -f for input regions).")
    group_advanced.add_argument('-r', dest='location', type=str, default='all',
                                choices=['all', 'promoter', 'distal', 'gene'],
                                help="Genomic location to apply MotifScan. "
                                     "'all': perform MotifScan on the all input regions. "
                                     "'promoter': perform MotifScan on regions which located at promoter regions. "
                                     "'distal': perform MotifScan on regions which located at distal regions. "
                                     "'gene': perform MotifScan on regions which is the target(nearest one) of genes "
                                     "within 10kbp distance cutoff.")
    group_advanced.add_argument('--upstream', dest='upstream', type=int, default=4000,
                                help="Upstream distance to TSS to define promoter regions. "
                                     "Valid when option -r is set as 'promoter' or 'distal'.")
    group_advanced.add_argument('--downstream', dest='downstream', type=int, default=2000,
                                help="Upstream distance to TSS to define promoter regions. "
                                     "Valid when option -r is set as 'promoter' or 'distal'.")
    group_advanced.add_argument('--random_times', dest='random_times', type=int, default=5,
                                help="The number of random control regions generated for each input region. For example,"
                                     " if you provide 1000 regions, 5000 random regions will be generated by default.")
    group_advanced.add_argument('--peak_length', dest='peak_length', type=int, default=1000,
                                help="The length of input regions to perform MotifScan around peak summit/midpoint. "
                                     "If set to 0, the whole peak region is used to perform MotifScan.")

    group_advanced.add_argument('--negative', dest='negative', action='store_true', default=False,
                                help='Using negative test of this pk')
    group_advanced.add_argument('--correction', dest='correction', default='benjamin',
                                help='correction type of pvalues, no correction or benjamin or bonferroni,'
                                     'default=benjamin')

    group_output = parser.add_argument_group("Output arguments")
    group_output.add_argument("-s", dest="output_all", action="store_true", default=False,
                              help="By default, MAnorm will output the results of unique and merged common peaks of "
                                   "two samples. With this option on, MAnorm will output two extra files containing "
                                   "the results of the original(unmerged) peaks in two samples. With this option on, "
                                   "MAmotif will also output the exact target sites of all motifs.")
    group_output.add_argument("-o", dest="output_prefix", type=str, required=True,
                              help="Comparison name, this is used as the folder name and prefix of output files.")

    return parser


def main():
    parser = argparser_config()
    args = parser.parse_args()
    peaks_file1 = args.peaks_file1
    peaks_file2 = args.peaks_file2
    reads_file1 = args.reads_file1
    reads_file2 = args.reads_file2
    shiftsize1 = args.shift_size1
    shiftsize2 = args.shift_size2
    peak_width = args.width
    if args.distance_cutoff:
        distance_cutoff = args.distance_cutoff
    else:
        distance_cutoff = peak_width / 2
    random_times = args.random_times
    overlap_dependent = args.overlap_dependent
    p_cutoff = args.p_cutoff
    m_cutoff = args.m_cutoff
    output_all = args.output_all
    output_name = args.output_prefix

    manorm_workflow.main(peaks_file1=peaks_file1, peaks_file2=peaks_file2, reads_file1=reads_file1,
                         reads_file2=reads_file2,
                         shift_size1=shiftsize1, shift_size2=shiftsize2, peak_width=peak_width,
                         distance_cutoff=distance_cutoff,
                         random_times=random_times, overlap_dependent=overlap_dependent, m_cutoff=m_cutoff,
                         p_cutoff=p_cutoff,
                         output_all=output_all, output_name=output_name)

    logging.basicConfig(level=logging.INFO, format="%(levelname)-8s @%(asctime)s: %(message)s", stream=sys.stderr,
                        datefmt="%m/%d/%Y %H:%M", filemode="w")
    genome_dir = args.genome
    gene_file = args.gene
    motif_file = args.motif
    motif_filter_file = args.motif_list
    peak_file = output_name + '/' + output_name + '_all_peaks_MAvalues.xls'
    peak_format = 'manorm'
    peak_length = args.peak_length
    control_file = None
    control_format = None
    location = args.location
    upstream = args.upstream
    downstream = args.downstream
    random_times = args.random_times
    enrichment_flag = args.enrichment_flag
    motifscan_run(genome_dir=genome_dir, gene_file=gene_file, motif_file=motif_file, motif_filter_file=motif_filter_file,
                  peak_file=peak_file, peak_format=peak_format, peak_length=peak_length, control_file=control_file,
                  control_format=control_format, location=location,
                  upstream=upstream, downstream=downstream, random_times=random_times, enrichment_flag=enrichment_flag,
                  target_site_flag=output_all, output_dir=output_name)

    mamotif_workflow.main(comparison_pk=peak_file, motifscan_result=output_name+'/'+'peak_motif_target_number.csv',
                          refgene_file=gene_file, correction_type=args.correction, neg=args.negative,
                          output_dir=output_name)


if __name__ == '__main__':
    main()
