#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import sys
import time
import logging
import argparse
from hichub.Constants import *

########################################################################
# HiCHub Modules
########################################################################

def main():
	"""The Main function/pipeline for hichub.
	"""
	# Parse options...
	argparser = prepare_argparser()
	args = argparser.parse_args()
	
	logging.basicConfig(level=logging.DEBUG,
						format='[%(asctime)s]: %(message)s ',
						datefmt='%Y-%m-%d %H:%M:%S',
						stream=sys.stdout,
						filemode="w"
						)    
	print("welcome")
	print("The python env is: " + sys.version)
	print("usage: hichub [-h] [-v] {test,diff,convert} ...")
	print("hichub -- A toolset to detect and analyze differential Hubs")
	print("positional arguments:")
	print("  {test,diff,convert}  sub-command help")
	print("    test               Output for test parser")
	print("    diff               Parser for diff hubs")
	print("    find               Parser for find gene in hubs")
	print("    plot               Parser for plot clusters")
    
	print("    convert            Convert multi .hic to txt format --> Format should be:")
	print("                       #chr bin1 bin2 Count")
	print("optional arguments:")
	print("  -h, --help           show this help message and exit")
	print("  -v, --version        show program's version number and exit")

	if (hasattr(args, 'outdir')):  # use a output directory to store HicHub output
		if not os.path.exists( args.outdir ):
			try:
				os.makedirs( args.outdir )
			except:
				sys.exit( "Output directory (%s) could not be created. Terminating program." % args.outdir )

## subcommand
	subcommand  = args.subcommand
	
	if subcommand == "convert":
		from hichub.convert_multi_hic_to_txt import run
		logging.info("This module can convert multiple .hic files into a txt")
		print('-' * 50)
		start_time = time.time()
		run( args )
		end_time = time.time()
		print('-' * 50)
		logging.info("Run complete: %s elapsed" % elapsed_time(start_time, end_time))

	elif subcommand == "diff":
		logging.info("Beginning HicHub diff hubs calling")
		print('-' * 50)
		start_time = time.time()
		from hichub.call_diff import run
		run( args )
		end_time = time.time()
		print('-' * 50)
		logging.info("Run complete: %s elapsed" % elapsed_time(start_time, end_time))

	elif subcommand == "plot":
		logging.info("Beginning plot clusters")
		print('-' * 50)
		start_time = time.time()
		from hichub.plot_cluster import run
		run( args )
		end_time = time.time()
		print('-' * 50)
		logging.info("Run complete: %s elapsed" % elapsed_time(start_time, end_time))

	elif subcommand == "find":
		logging.info("Beginning find gene hubs")
		print('-' * 50)
		start_time = time.time()
		from hichub.find_gene import run
		run( args )
		end_time = time.time()
		print('-' * 50)
		logging.info("Run complete: %s elapsed" % elapsed_time(start_time, end_time))

	elif subcommand == "test":
		logging.info("Beginning Test run")
		print('-' * 50)
		start_time = time.time()
		from hichub.test import run
		run( )
		end_time = time.time()
		print('-' * 50)
		logging.info("Run complete: %s elapsed" % elapsed_time(start_time, end_time))
	return argparser


def prepare_argparser():
	"""
	Prepare optparser object. New options will be added in this function first.
	"""
	description = "%(prog)s -- A toolset to detect and analyze differential Hubs"
	epilog = "For command line options of each command, type: %(prog)s COMMAND -h"
	# top-level parser
	parser = argparse.ArgumentParser( description = description, epilog = epilog)
	parser.add_argument("-v", "--version", action="version", version="%(prog)s "+ hichub_VERSION)
	
	subparsers = parser.add_subparsers( dest = 'subcommand', 
	help='sub-command help' 
	)

	# command for 'test'
	add_test_parser( subparsers )
	# command for 'diff'
	add_diff_parser( subparsers )
	# command for 'convert'
	add_convert_parser( subparsers )
    # command for 'plot'
	add_plot_parser( subparsers )
    # command for 'find gene'
	add_find_parser( subparsers )
	
	return parser

def add_outdir_option( parser ):
	parser.add_argument("--outdir", dest = "outdir", type = str, default = '',
						help = "If specified all output files will be written to that directory. Default: the current working directory")


def add_test_parser( subparsers ):
	"""
	Add test function 'test' argument parsers.
	"""
	parser_test = subparsers.add_parser("test", help = "Output for test parser")
	## detail in subparser
	test_parser_group = parser_test.add_argument_group( "general arguments" )
	test_parser_group.add_argument( "-g", "--GTF-file", dest = "inputfile",
	metavar = "GTFFILE", type = str, required = True, help = "Input annotation GTF filename. REQUIRED." )
	return

def add_convert_parser( subparsers ):
	"""
	Convert multi .hic to txt format --> Format should be: #chr	bin1	bin2	Count"
	"""
	parser_tem = subparsers.add_parser("convert", help = "Convert multi .hic to txt format --> Format should be: #chr	bin1	bin2	Count")
	## detail in subparser
	parser_tem_group = parser_tem.add_argument_group( "general arguments" )
	
	parser_tem_group.add_argument("-i", "--in", action="store", type=str, required = True,
		dest="input_path", help="Path to Input HiC file in .hic format", metavar="<file>")
	
	parser_tem_group.add_argument("-n", "--norm", action="store", type=str, 
		dest="norm_hic", help="Norm of .hic file you are going to apply.", metavar="<str>")
		
	parser_tem_group.add_argument("-f", "--file_name", action="store", type=str, required = True,
		dest="file_name", help="Name of File. Delimiter ',', for example 'file1,file2' ", metavar="<str>")
		
	parser_tem_group.add_argument("-l", "--file_label", action="store", type=str, required = True,
		dest="file_label", help="Name of File.Delimiter ',', for example 'label1,label2'", metavar="<str>")
		
	parser_tem_group.add_argument("-r", "--resolution", action="store", type=int, required = True,
		dest="res", help="Resolution of HiC txt", metavar="<int>")
	
	return 


def add_plot_parser( subparsers ):
	"""
	Module for Diff Hubs argument parsers.
	"""
	parser_plot = subparsers.add_parser("plot", help = "Parser for plot clusters")
	## detail in subparser
	plot_parser_group = parser_plot.add_argument_group( "general arguments" )
	
	plot_parser_group.add_argument("-i", "--in", action="store", type=str, required = True,
		dest="input_path", help="Path to Input HiC file in txt format", metavar="<file>")
	
	plot_parser_group.add_argument("-c", "--cluster", action="store", type=str, required = True,
		dest="cluster_path", help="Path to cluster file", metavar="<file>")
		
	plot_parser_group.add_argument("-n", "--gene name", action="store", type=str, required = True,
		dest="gene_name", help="Name of gene.", metavar="<str>")
		
	plot_parser_group.add_argument("-f", "--foreground_name", action="store", type=str, required = True,
		dest="fore_name", help="Name of condition as foreground.", metavar="<str>")
		
	plot_parser_group.add_argument("-b", "--background_name", action="store", type=str, required = True,
		dest="back_name", help="Name of condition as background.", metavar="<str>")
	
	return

def add_find_parser( subparsers ):
	"""
	Module for find gene in Hubs argument parsers.
	"""
	parser_tem = subparsers.add_parser("find", help = "Find gene in hubs.")
	## detail in subparser
	parser_tem_group = parser_tem.add_argument_group( "general arguments" )
	
	parser_tem_group.add_argument("-i", "--in", action="store", type=str, required = True,
		dest="input_path", help="Path to Input HiC file in .hic format", metavar="<file>")
	
	parser_tem_group.add_argument("-n", "--gene", action="store", type=str, 
		dest="gene_name", help="Name of gene.", metavar="<str>")
		
	parser_tem_group.add_argument("-f", "--file_name", action="store", type=str, required = True,
		dest="file_name", help="Name of File. Delimiter ',', for example 'file1,file2' ", metavar="<str>")
		
	parser_tem_group.add_argument("-l", "--file_label", action="store", type=str, required = True,
		dest="file_label", help="Name of File.Delimiter ',', for example 'label1,label2'", metavar="<str>")

	
	return

def add_diff_parser( subparsers ):
	"""
	Module for Diff Hubs argument parsers.
	"""
	parser_diff = subparsers.add_parser("diff", help = "Parser for diff hubs")
	## detail in subparser
	diff_parser_group = parser_diff.add_argument_group( "general arguments" )
	
	diff_parser_group.add_argument("-i", "--in", action="store", type=str, required = True,
		dest="input_path", help="Path to Input HiC file in txt format", metavar="<file>")
	
	diff_parser_group.add_argument("-f", "--foreground_name", action="store", type=str, required = True,
		dest="fore_name", help="Name of condition as foreground.", metavar="<str>")
		
	diff_parser_group.add_argument("-b", "--background_name", action="store", type=str, required = True,
		dest="back_name", help="Name of condition as background.", metavar="<str>")
		
	diff_parser_group.add_argument("-c", "--cut_off", action="store", type=float,  default = 10, required = False, dest="cut_off_value", help="cut-off value for sum of row counts", metavar="<int>")
    
	diff_parser_group.add_argument("-d", "--FC", action="store", type=float, required = True, default = 1.0,required = False,
		dest="foldchange", help="Optional: FC to evaluate qualified difference, default=1.0", metavar="<int>")
	
	diff_parser_group.add_argument("-p", "--pvalue", action="store", type=float, required = False,
		default=0.00001, dest="pvalue", help="Optional: pvalue cutoff for output (diff hub)", metavar="<float>")
		
	diff_parser_group.add_argument("-t", "--num_threads", action="store", type=int, required = False,
		default=1, dest="thread", help="Optional: Number of threads to run, default=1", metavar="<int>")
	
	return


def elapsed_time(start_time, end_time):
	elapsed_sec = end_time - start_time
	h = int(elapsed_sec / (60 * 60))
	m = int((elapsed_sec % (60 * 60)) / 60)
	s = int(elapsed_sec % 60)
	return "{}:{:>02}:{:>02}".format(h, m, s)


if __name__ == '__main__':
	try:
		main()
	except KeyboardInterrupt:
		sys.stderr.write("User interrupted me!\n")
		sys.exit(0)
