#!/usr/bin/env python3
#########################################################
## Jose F. Sanchez										##
## Copyright (C) 2019 Lauro Sumoy Lab, IGTP, Spain		##
##########################################################
"""
Sets configuration of the pipeline.

This module relies in several scripts and files which are arranged in the 
``BacterialTyper/config`` :doc:`folder <../config/config_index>`:	

	- :doc:`BacterialTyper/config/set_config.py <../config/set_config>`

	- :doc:`BacterialTyper/config/extern_progs.py <../config/extern_progs>`

	- :doc:`BacterialTyper/config/install_dependencies.py <../config/install_dependencies>`

	- Additional information and specifications :doc:`details <../config/additional_info>`.	

.. seealso:: Additional information on BacterialTyper configuration and requirements

	- :doc:`Installation <../../user_guide/installation/installing>`
	
	- :doc:`Requirements <../../user_guide/installation/requirements>` 

	- :doc:`Configuration <../../user_guide/modules/config>`

"""
## useful imports
import time
import io
import os
import sys
from termcolor import colored
from distutils.version import LooseVersion

## import my modules
from BacterialTyper.config import set_config
from BacterialTyper.config import extern_progs
from BacterialTyper.scripts import functions
from BacterialTyper.config import install_dependencies

def run(options):
	"""
	This is the main function of the module ``config``. It basically checks 
	if the different requirements (python` and third-party software) are
	fulfilled. 

	If any requirement is not available this modules tries to install them or reports to the user to
	manually install them.

	:param option: State whether to check or install missing modules, packages and third party software. Provide: check/install
	:param install_path: Absolute path to install modules or packages missing. Default: ``BacterialTyper`` environment path.
	:param IslandPath: True/False for checking additional perl and software required by this option analysis.
	:param debug: True/false for debugging messages.
	
	:type option: string 
	:type IslandPath: boolean
	:type install_path: string 
	:type debug: boolean	

	.. seealso:: This function depends on several ``BacterialTyper`` functions:

		- :func:`BacterialTyper.config.set_config.check_python_packages`

		- :func:`BacterialTyper.config.set_config.check_perl_packages`

		- :func:`BacterialTyper.config.extern_progs.return_min_version_soft`

		- :func:`BacterialTyper.config.extern_progs.print_dependencies`

	"""

	## init time
	start_time_total = time.time()

	## debugging messages
	global Debug
	if (options.debug):
		Debug = True
	else:
		Debug = False

	functions.pipeline_header()
	functions.boxymcboxface("Pipeline Configuration")
	print ("--------- Starting Process ---------")
	functions.print_time()

	if (options.install_path):
		if os.path.isdir(options.install_path):
			if (Debug):
				print ("Installation path provided for missing modules, packages, dependencies...")
				print ("Path: " + options.install_path)
		else:
			print (colored("\n*** ERROR ****", 'red'))
			print (colored("Path provided is not a folder", 'red')) 
			print (options.install_path)
			exit()
	else:
		## get python environment path
		env_bin_directory = os.path.dirname(os.environ['_'])

		##os.path.abspath(os.path.join(os.path.dirname( __file__ ), '..', 'templates'))
		options.install_path = os.path.abspath(os.path.join(env_bin_directory, '../software'))

		if (Debug):
			print ("Retrieve environment path as installation path:")
			print ("Path: " + options.install_path)

		functions.create_folder(options.install_path)

	## install or only check
	option_install = False
	if (options.option == 'install'):
		print ("\n+ Check dependencies")
		print ("+ Try to install all missing dependencies, modules or third party software...")
		option_install = True

		## check if access and permission
		if os.path.isdir(options.install_path):
			if (set_config.access_check(options.install_path, mode=os.F_OK)):
				print ("Installation path is accessible and has permission for installation if necessary")
			else:
				print (colored("\n*** ERROR ****", 'red'))
				print (colored("No access/permission for this path: %s" %options.install_path, 'red'))
				print (colored("Please provide a valid path with access/permission to install any missing dependencies.", 'red'))
				exit()
		else:
			print (colored("\n*** ERROR ****", 'red'))
			print (colored("Path provided is not a folder", 'red'))
			print (options.install_path)
			exit()

	elif (options.option == 'only_check'):
		print ("\nCheck dependencies, modules or third party software and print report...")

	## python version
	functions.print_sepLine("+", 20, False)
	print ('Python:')
	functions.print_sepLine("+", 20, False)

	this_python_version = str(sys.version)
	python_min_version = extern_progs.return_min_version_soft('python')
	if LooseVersion(this_python_version) >= LooseVersion(python_min_version):
		print (colored("Minimum version (%s) satisfied: %s" %( python_min_version, this_python_version), 'green'))
	else:
		print (colored("Minimum version (%s) not satisfied: %s" %(python_min_version, this_python_version), 'red'))
		exit()
		
	## perl_version
	print ('\n')
	functions.print_sepLine("+", 50, False)
	print ('Perl:')
	functions.print_sepLine("+", 50, False)
	
	perl_min_version = extern_progs.return_min_version_soft('perl')
	this_perl_path = set_config.get_exe("perl", Debug)
	this_perl_version = set_config.get_version("perl", this_perl_path, Debug)
	if LooseVersion(this_perl_version) >= LooseVersion(perl_min_version):
		print (colored("Minimum version (%s) satisfied: %s" %(perl_min_version, this_perl_version), 'green'))
	else:
		print (colored("Minimum version (%s) not satisfied: %s" %(perl_min_version, this_perl_version), 'red'))
		exit()

	## third-party software
	print ('\n')
	functions.print_sepLine("+", 20, False)
	print ('External dependencies:')
	functions.print_sepLine("+", 20, False)
	
	set_config.check_dependencies(option_install, options.install_path, Debug)
	print ('\n')	

	## python packages
	print ('\n')
	functions.print_sepLine("+", 20, False)
	print ('Python packages:')
	functions.print_sepLine("+", 20, False)

	set_config.check_python_packages(Debug, option_install, options.install_path)
	functions.print_sepLine("+", 20, False)
	print ('\n')

	## perl packages
	print ('\n')
	functions.print_sepLine("+", 20, False)
	print ('Perl packages:')
	functions.print_sepLine("+", 20, False)

	set_config.check_perl_packages("perl_dependencies", Debug, option_install, options.install_path)
	functions.print_sepLine("+", 20, False)
	print ('\n')

	## IslandPath dependencies
	if (options.IslandPath):
		print ('\n')
		functions.print_sepLine("+", 20, False)
		print ('IslandPath packages and software required:')
		functions.print_sepLine("+", 20, False)
	
		set_config.check_IslandPath(Debug, option_install, options.install_path)
		functions.print_sepLine("+", 20, False)
		print ('\n')


	## R packages
	print ('\n')
	functions.print_sepLine("+", 20, False)
	print ('R packages:')
	functions.print_sepLine("+", 20, False)

	set_config.check_R_packages(option_install, options.install_path, Debug)
	functions.print_sepLine("+", 20, False)
	print ('\n')
