#!/usr/bin/env python3

'''
This script is used to generate an installation report in pdf format.
Installation Report PDF generated by this script contains the following information:
vCenter Details
Nodes' Details like Name, IP Address, Hypervisor
Logging Service Details
Consul & Vault Service Details
IBE Service Details
VM information
'''
import argparse
import yaml
import socket
import jinja2
import sys
from datetime import datetime
import pdfkit
import os
import logging
import hcl
import configparser
from time import strftime
from ansible.parsing.dataloader import DataLoader
from ansible.inventory.manager import InventoryManager
from . logging_monitoring_details import LoggingMonitoringDetails
from . vmware_details import VmwareDetails
from . hsop_services import HsopServices
from . hsop_version import HsopVersion
from . import global_vars

HsopVersion = HsopVersion()
HsopServices = HsopServices()
VmwareDetails = VmwareDetails()
LoggingMonitoringDetails = LoggingMonitoringDetails()

def get_inventory_details():
    if not os.path.exists(global_vars.INVENTORY_FILE):
        log_and_raise_exception('Inventory file {0} does not exist'.format(global_vars.INVENTORY_FILE))
    logging.debug('Parsing Inventory file {0}'.format(global_vars.INVENTORY_FILE))
    data_loader = DataLoader()
    inventory = InventoryManager(loader = data_loader,sources=[global_vars.INVENTORY_FILE])
    return inventory.get_groups_dict()

def get_config_details(CONFIG_FILE):
    if not os.path.exists(CONFIG_FILE):
        log_and_raise_exception('Conf file {0} does not exist'.format(CONFIG_FILE))
    logging.debug('Parsing config file {0}'.format(CONFIG_FILE))
    with open(CONFIG_FILE, 'r') as fp:
        config = yaml.safe_load(fp)
        return config

def get_ansible_cfg(ANSIBLE_CFG):
   if not os.path.exists(ANSIBLE_CFG):
      log_and_raise_exception('Conf file {0} does not exist'.format(ANSIBLE_CFG))
   logging.debug('Parsing config file {0}'.format(ANSIBLE_CFG))
   configParser = configparser.RawConfigParser()
   configParser.read(ANSIBLE_CFG)
   ansible_cfg = dict(configParser.items('defaults'))
   return ansible_cfg

def get_values_for_report(config_dict,inventory_dict,ansible_dict,BUILD_CONF,ansible_vars_dict,hsop_repoPath):
    '''
    Gets the data needed to fill the report template.
    Data includes vCenter information, Core service details

    '''
    hsop_version=HsopVersion.get_hsop_version(inventory_dict,config_dict,BUILD_CONF)
    logging.debug('Getting Values for the report template')
    report_values = {}
    report_generation_time = datetime.now().strftime("%d-%m-%Y %H:%M:%S")
    report_values['report_generation_time'] = report_generation_time
    logging.debug('Report ie being generated at {0}'.format(report_generation_time))
    infra_details={}   
    vmware_infra_details = VmwareDetails.get_infra_details_for_report(config_dict)
    report_values.update(vmware_infra_details)
    service_details = HsopServices.get_service_details(config_dict, inventory_dict, ansible_dict, ansible_vars_dict, hsop_repoPath)
    report_values['service_details'] = service_details
    report_values['iac_deployment_time'] = LoggingMonitoringDetails.get_deployment_time_for_logging(config_dict)
    report_values['hsop_serialId'] = config_dict['hsop_serial_number']
    report_values['vcip'] = socket.gethostbyname(config_dict['vsphere_server'].strip('\"'))
    logging.debug('Values for the report : {0}'.format(report_values))
    report_values['hsop_version'] = hsop_version
    return report_values

def generate_report_in_html(repo_path,report_values, html_file):
    '''
    Updates the HTML report template with values and generates report in HTML format
    :param report_values
    :param html_file
    '''
    logging.debug('Started generating report in HTML')
    templateLoader = jinja2.FileSystemLoader(searchpath=repo_path+"/dhr/dhrpackage/template")
    templateEnv = jinja2.Environment(loader=templateLoader)
    TEMPLATE_FILE = "installation_report_template.html.j2"
    template = templateEnv.get_template(TEMPLATE_FILE)
    output_text = template.render(report_values)
    html_file = open(html_file, 'w')
    html_file.write(output_text)
    html_file.close()
    logging.debug('Completed generating report in HTML')

def generate_report_in_pdf(html_file, pdf_file):
    '''
    Generates report in PDF fromat from HTML file
    :param html_file
    :param pdf_file
    '''
    logging.debug('Generating report in pdf format')
    config = pdfkit.configuration()
    pdfkit.from_file(html_file, pdf_file, configuration=config)
    logging.debug('Completed generation of report in pdf format')

def log_and_raise_exception(err_msg):
    '''
    Logs the error message and raises an exception
    :param err_msg
    '''
    logging.error(err_msg)
    raise Exception(err_msg)

def main():
    '''
        Entry method for the script
        :return: None
    '''   
    parser = argparse.ArgumentParser(description='DHR with repo path as input parameters.Example:python __main__.py  /home/hsop-svc/HSOP')
    parser.add_argument("HSOPRepoPath", help="Absolute Path for HSOP repo. Ex: /home/hsop-svc/HSOP")
    args = parser.parse_args()
    if len(sys.argv) == 1:
       os.system("python " + sys.argv[0] + " -h")
       exit()	
    BUILD_CONF  = args.HSOPRepoPath+"/build_version.conf"
    logs_path = args.HSOPRepoPath+"/dhr/logs"
    reports_path = args.HSOPRepoPath+"/dhr/reports"
    try:
        os.makedirs(logs_path, exist_ok=True)
    except Exception as e:
        print('Exception occurred while creating directory {0} : {1}'.format(logs_path, str(e)))
        sys.exit(1)
    logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(levelname)s %(message)s',
                        handlers=[
                            logging.FileHandler("{0}/{1}".format(logs_path, strftime("{0}_{1}.log".format(global_vars.REPORT_PREFIX, global_vars.REPORT_SUFFIX_FORMAT)))),
                            logging.StreamHandler()
                        ])
    try:
        os.makedirs(reports_path, exist_ok=True)
    except Exception as e:
        log_and_raise_exception('Exception occurred while creating directory {0} : {1}'.format(global_vars.reports_path, str(e)))
    html_file_name = '{0}_{1}.html'.format(global_vars.REPORT_PREFIX, datetime.now().strftime(global_vars.REPORT_SUFFIX_FORMAT))
    html_file = os.path.join(reports_path, html_file_name)
    pdf_file = html_file.replace('html', 'pdf')
    inventory_dict = get_inventory_details()
    config_dict = get_config_details(args.HSOPRepoPath+global_vars.INPUT_VAR_FILE)
    ansible_dict = get_ansible_cfg(args.HSOPRepoPath+global_vars.ANSIBLE_CFG)
    ansible_vars_dict = get_config_details(args.HSOPRepoPath+global_vars.ANSIBLE_VAR_FILE)
    report_values = get_values_for_report(config_dict, inventory_dict, ansible_dict, BUILD_CONF, ansible_vars_dict, args.HSOPRepoPath)
    generate_report_in_html(args.HSOPRepoPath, report_values, html_file)
    generate_report_in_pdf(html_file, pdf_file)
    logging.debug('Report {0} has been generated successfully'.format(pdf_file))
    print(html_file_name)
    sys.exit(0) 
   
if __name__ == '__main__':
    main()
