#!/usr/bin/env python
# -*- coding: utf-8 -*-
##
#
# Vaisala software source code file
#
# Copyright (c) Vaisala Oyj 2016. All rights reserved.
#
##
import argparse

from installer_utils import *

_logger = logging.getLogger('rsw-upgrade')
FROM_VERSION = u"2.0.0"
VERSION = u"2.1.0"
PACKAGES = [
    'vaisala-radarsw-webapp',
    'vaisala-radarsw-webapp-proxy',
    'vaisala-radarsw-monitoring',
    'vaisala-radarsw-backup',
    'vaisala-radarsw-scan-service'
]


def check_installed_version(current_version, skip_version_check):
    dbg(u"Identifying the currently installed version of IRIS Focus.")
    if not current_version.strip():
        log_and_exit(u"Can not upgrade because no previous version of IRIS Focus is installed." +
                     u"\nUpgrade is only possible from version {}".format(FROM_VERSION), _logger)
    if not skip_version_check and current_version != FROM_VERSION:
        log_and_exit(u"Can not upgrade from {} to {}".format(current_version, VERSION), _logger)


def create_prerequisite_steps(args):
    steps = [
        PreFunctionStep(lambda: ensure_run_by_root(), u"Check if invoked by root user"),
        PreFunctionStep(lambda: ensure_correct_centos_version(args.skip_os_version_check),
                        u"Check if correct operating system version"),
        PreFunctionStep(lambda: ensure_good_path_environment(_logger), u"Configure PATH"),
        PreFunctionStep(lambda: check_installed_version(resolve_webapp_version(), args.skip_version_check),
                        u"Check IRIS Focus version"),
        PreFunctionStep(lambda: log_system_information(_logger), u"Log system information"),
        create_hostname_resolvable_step(_logger),
        make_verify_executable_is_callable_step(u"rsw-rpm-radarsw-repo-create", _logger)
    ]

    return steps


def create_post_steps():
    return [create_remove_yum_cache_step(_logger)]


def create_steps():
    return [
        ShellCommandStep(["/usr/vaisala/radarsw/backup/bin/do-backups"],
                         u"Back up configuration and database",
                         help_message=u"""
Could not take backups before upgrading. For more information,
take a look at the log file in '/var/log/vaisala/radarsw/backup.log'.""", logger=_logger),
        ShellCommandStep(["rsw-rpm-radarsw-repo-create"], u"Install 'radarsw' Yum repo", logger=_logger),
        ShellCommandStep(["rsw-package-available", VERSION] + PACKAGES,
                         u"Check if rpm packages are available", logger=_logger),
        ShellCommandStep(["service", "monit", "stop"], u"Stop service monitoring daemon monit", logger=_logger),
        ShellCommandStep(['yum', '-y', 'upgrade'] + PACKAGES, u"Install RPM packages",
                         help_message=
                         """Couldn't install packages. If you encountered a problem with Yum repos being
                         offline, try disabling all repos that have 0 packages available or when you
                         encounter an error such as 'Cannot find a valid baseurl for repo: <repo-id>'.

                         You can list all enabled repos with command
                          - yum repolist enabled

                         You'll see the package count on the rightmost column. You can disable the repo
                         by calling
                          - yum-config-manager --disable <repo-id>
                         where <repo-id> is the left-most column in the previous listing.""", logger=_logger),
        ShellCommandStep(["service", "monit", "start"], u"Restart service monitoring daemon monit", logger=_logger),
    ]


def log(*args, **kwargs):
    return _logger.info(*args, **kwargs)


def dbg(*args, **kwargs):
    return _logger.debug(*args, **kwargs)


def _log_title(title):
    log(u"#" * LINE_LENGTH)
    log(u"# " + title)
    log(u"#" * LINE_LENGTH)


def setup_logging(debug, dry_run):
    _logger.setLevel(logging.DEBUG)

    sout_h = logging.StreamHandler(sys.stdout)
    if debug:
        sout_h.setLevel(logging.DEBUG)
    else:
        sout_h.setLevel(logging.INFO)
    _logger.addHandler(sout_h)

    log_file = os.path.join(os.environ['HOME'], u"rsw-upgrade-{0}.log".format(time.strftime("%Y%m%d-%H%M%S")))
    file_h = logging.FileHandler(log_file)
    file_h.setLevel(logging.DEBUG)
    _logger.addHandler(file_h)

    if not dry_run:
        log(u"Logging to stdout and to '{0}'.".format(log_file))
    return log_file


def create_arg_parser():
    parser = argparse.ArgumentParser('rsw-upgrade',
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    # Optional arguments
    opt_group = parser.add_argument_group("optional arguments")
    opt_group.add_argument("-d", "--debug", dest="debug", action="store_true", help="Enable debug messages")
    opt_group.add_argument("--dry-run", dest="dry_run", action="store_true", default=False,
                           help="Don't do anything, just list the steps that would be run.")
    opt_group.add_argument("--skip-os-version-check", dest="skip_os_version_check", default=False, action="store_true",
                           help=u"Skip operating system version check. " +
                                u"IRIS Focus is officially supported only on CentOS 7.1.")
    opt_group.add_argument("--skip-version-check", dest="skip_version_check", default=False, action="store_true",
                           help=u"Skip IRIS Focus version check and force upgrade. Used for testing.")

    return parser


def main():
    parser = create_arg_parser()
    args = parser.parse_args()
    log_file = setup_logging(args.debug, args.dry_run)

    pre_steps = create_prerequisite_steps(args)
    steps = create_steps()

    status = u"FAILED"
    try:
        _log_title(u"Pre-upgrade checks")
        StepExecutor(pre_steps, _logger, args.dry_run).execute()
        _log_title(u"Upgrade")
        StepExecutor(steps, _logger, args.dry_run).execute()
        status = u"SUCCESSFUL"
    finally:
        if args.dry_run:
            _log_title(u"# Dry run complete")
        else:
            log(u"\n" + (u"#" * LINE_LENGTH))
            log(u"# Upgrade " + status + u". Log: {}".format(log_file))
            log(u"#" * LINE_LENGTH)
            if status == u"SUCCESSFUL":
                log(u"\nIRIS Focus {} requires a new license. ".format(VERSION) +
                    u"\nPlease contact your sales representative to get one.")


if __name__ == '__main__':
    try:
        main()
    finally:
        try:
            remove_radarsw_repo(_logger)
        except:
            pass
