# Copyright 2016 VMware, Inc.
# All rights reserved. -- VMware Confidential
"""
The module contains common patching functionality for VMware vCenter services.
The component should act similarly as visl-integration does in firstboot
execution and should be executed just before all other components.
"""
import sys
import os
import json
import platform
import logging

from patch_specs import DiscoveryResult, ValidationResult, Question, Mismatch, Requirements, PatchInfo,\
    RequirementsResult
from extensions import extend, Hook
from l10n import msgMetadata as _T, localizedString as _
import vcsa_utils
from os_utils import executeCommand

logger = logging.getLogger(__name__)
MY_PAYLOAD_DIR = os.path.dirname(__file__)


@extend(Hook.Discovery)
def discover(ctx): #pylint: disable=W0613
    '''DiscoveryResult discover(PatchContext sharedCtx) throw UserUpgradeError'''

    return vcsa_utils.getComponentDiscoveryResult("vmware-cis-config",
                                                  displayName=_(_T("common.comp.displayName",
                                                                   "VMware vCenter Server Patcher")))

@extend(Hook.Requirements)
def collectRequirements(ctx): #pylint: disable=W0613
    '''RequirementsResult collectRequirements(PatchContext sharedCtx)'''
    mismatches = []
    requirements = Requirements()
    patchInfo = PatchInfo()

    return RequirementsResult(requirements, patchInfo, mismatches)

@extend(Hook.Validation)
def validate(ctx): #pylint: disable=W0613
    '''ValidationResult validate(PatchContext sharedCtx)'''
    mismatches = []

    return ValidationResult(mismatches)

@extend(Hook.Prepatch)
def prePatch(ctx): #pylint: disable=W0613
    '''void prePatch(PatchContext sharedCtx) throw UserUpgradeError'''
    pass

def _getStagedScript(ctx, scriptName):
    '''Gets location of the script downloaded to staged directory.

    @param ctx: Patch context shared among all patching hooks
    @type ctx: PatchContext

    @param scriptName: Name of the script
    @type scriptName: str

    @return: The full path location on the disk
    @rtype: str
    '''
    # Stage directory points to $STAGE_DIR/patch_runner/<compName> defined in
    # update_script.py
    stageDir = ctx.stageDirectory
    result = os.path.abspath(os.path.join(stageDir, os.pardir, os.pardir,
                                          "scripts", scriptName))
    return result

def _executeThirdPartyPrePatchScript(scriptLocation):
    '''Executes third party pre-patch script. The script contains update logic
    necessary to be executed just after all rpms are installed, and just before
    the components patch hook is get called.

    @param scriptLocation: Location to the script which needs to be executed
    @type scriptLocation: str
    '''
    logger.info("Running pre-patch script %s", scriptLocation)
    stdout, stderr, exitCode = executeCommand([scriptLocation])
    logger.info("pre-patch script completed. Stdout=%s,Stderr=%s,exit-code=%s",
                stdout, stderr, exitCode)
    if exitCode:
        raise Exception("Unable to execute script %s", scriptLocation)

@extend(Hook.Patch)
def patch(ctx): #pylint: disable=W0613
    '''void patch(PatchContext sharedCtx) throw UserUpgradeError'''
    prePatchScript = _getStagedScript(ctx, "pre-patch.sh")
    _executeThirdPartyPrePatchScript(prePatchScript)
