#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (C) 2013-2018:
# This file is part of Shinken Enterprise, all rights reserved.

import optparse
import sys
import os
import re
import tarfile

try:
    import shinken
except ImportError:
    print 'Cannot import shinken lib, please install it before launching this tool'
    sys.exit(2)

from shinkensolutions.system_tools import run_command
from shinken.objects.config import Config
from shinkensolutions.localinstall import ERROR_SHELL_TAG, RESET_SHELL_TAG

STOP_SYNCHRONIZER = 'service shinken-synchronizer stop'
START_SYNCHRONIZER = 'service shinken-synchronizer start'
MONGORESTORE = 'mongorestore --drop %s'
REGEX_BACKUP_NAME = r'^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}-[0-9]{2}_.*\.tgz$'


# If there is a critical error: print it in RED and exit in bad state
def exit_error(txt, parser=None):
    print "%sERROR: %s%s" % (ERROR_SHELL_TAG, txt, RESET_SHELL_TAG)
    if parser:
        parser.print_help()
    sys.exit(2)


def init_conf(config_file):
    # Get the configuration
    conf = Config()
    conf.read_config_silent = 1
    buf = conf.read_config([config_file])
    raw_objects = conf.read_config_buf(buf)
    conf.create_objects_for_type(raw_objects, 'module')
    
    conf_module = None
    for module in conf.modules.items.itervalues():
        if module.module_type == 'synchronizer_module_database_backup':
            conf_module = module
            break
    
    if not conf_module:
        exit_error('Any "synchronizer-module-database-backup" were found')
    
    return conf_module


def choose_archive(backup_directory):
    archives = sorted([arch for arch in os.listdir(backup_directory) if re.match(REGEX_BACKUP_NAME, arch)])
    archive_counter = len(archives) - 1
    error_message = 'This choice is not available ! Please retry with a number between 0 and %s' % (archive_counter)
    selected_archive = None
    
    print 'Theses backup were found : '
    for i, file in enumerate(archives):
        print '\t[%3d] %s' % (i, file)
    
    try:
        choice = input('Which backup do you want to restore ? [%s-%s] : ' % (0, archive_counter))
        choice = int(choice)
        if not (0 <= choice <= archive_counter):
            raise ValueError
        selected_archive = archives[choice]
        print 'Will restore the %s' % selected_archive
    except (ValueError, NameError, SyntaxError, IndexError):
        exit_error(error_message)
    
    return selected_archive


def untar_backup(directory, backup):
    cwd = os.getcwd()
    os.chdir(directory)
    tar = tarfile.open(backup)
    tar.extractall()
    tar.close()
    os.chdir(cwd)


def mongo_restore(directory, selected_archive):
    print 'Restore mongo database.'
    cwd = os.getcwd()
    os.chdir(directory)
    run_command(MONGORESTORE % selected_archive.split('.tgz')[0])
    os.chdir(cwd)
    print 'Database restored ! you can restart your synchronizer'


def ask_for_confirmation(question, exit_log=None):
    answer = raw_input(question)
    if type(answer) != str:
        exit_error('Your answer is not valid. Please use one of ')
    if answer in ['Y', 'y', 'O', 'o']:
        return True
    if exit_log:
        exit_error(exit_log)
    else:
        return False


def main():
    parser = optparse.OptionParser(description='This tool is used to restore the configuration database')
    parser.add_option('-c', '--config-file', dest='config_file', default='/etc/shinken/shinken.cfg', help='To specify a shinken configuration file. You can specify the synchronizer-module-database-backup file [default : /etc/shinken/shinken.cfg].')
    
    opts, args = parser.parse_args()
    
    conf_module = init_conf(opts.config_file)
    
    selected_archive = choose_archive(conf_module.backup_directory)
    
    print 'Will stop the synchronizer to restore the database.'
    ask_for_confirmation('Do you want to stop the synchronizer now ? [y/N] : ', 'The backup wasn\'t restored. Please launch this script again when you can stop the synchronizer.')
    ret = run_command(STOP_SYNCHRONIZER)
    print ret
    
    untar_backup(conf_module.backup_directory, selected_archive)
    
    mongo_restore(conf_module.backup_directory, selected_archive)
    
    print "The backup [%s] was sucessful restored." % selected_archive
    
    if ask_for_confirmation('Do you want to start the synchronizer now ? [y/N] : '):
        ret = run_command(START_SYNCHRONIZER)
        print ret
    else:
        print 'You can start your synchronizer with the command : %s' % START_SYNCHRONIZER


if __name__ == '__main__':
    main()
