# Copyright 2019 VMware, Inc.
# All rights reserved. -- VMware Confidential

"""
    The purpose of this script is to run the specific for WCP prechecks during
    patching. Due to the way WCP code is structure do not import and call
    functions except the 'performWcpPrechecks' which has the logic to start the
    WCP in new process to prevent messing the python path.
"""

import sys
import logging
import os
from queue import Empty
from multiprocessing import Process, Queue

from update_utils import DEPLOYMENT_ROOT
from vmware.update.json_utils import JsonSerializer
from vmware.update.specs import InternalError

logger = logging.getLogger(__name__)


def doWcpPrechecks(resultQueue, requirementsSpec):
    ''' THIS SHOULD ONLY BE CALLED VIA MULTIPROCESSING MODULE as there is clash
    in WCP and applmgmt packages, both have package "vmware"
    '''
    logger.info("Performing WCP checks")
    wcpFolder = os.path.join(DEPLOYMENT_ROOT, "scripts", "patches",
                             "payload", "components-script", "wcp")

    logger.info("Adding WCP path to Python path")
    sys.path.append(wcpFolder)

    # Not all frameworks have that property set yet so we need to check this
    # way
    skipPrechecksIds = []
    if hasattr(requirementsSpec, 'skipPrechecksIds'):
        skipPrechecksIds = requirementsSpec.skipPrechecksIds

    result = []  # List of Mismatches to be returned
    ex = None  # To hold exception if raised.
    try:
        sys.path.append(os.path.join(
            os.path.dirname(__file__),
            "patches",
            "payload",
            "components-script",
            "wcp"))
        import precheck
        result = precheck.doPrecheck(skipPrechecksIds)
    except Exception as e:
        logger.exception("Exception raised while running wcp prechecks.")
        ex = e

    json_result = JsonSerializer().serialize([result, ex])
    resultQueue.put(json_result)
    logger.info("Done performing WCP checks")


def performWcpPrechecks(requirementsSpec):
    ''' This performs specific to the WCP checks that should block the patching
    @param requirementsSpec: The requirements hook input
    @type requirementsSpec:

    @return: list of mismatches if any
    @rtype: list(Mismatch)
    '''
    logger.info("About to perform WCP checks")
    resultQueue = Queue()
    p = Process(target=doWcpPrechecks, args=(resultQueue, requirementsSpec))
    p.start()

    # Blocks until the process does not complete
    p.join()

    try:
        json_result = resultQueue.get_nowait()
        result, ex = JsonSerializer().deserialize(json_result)
        if ex:
            raise ex
    except Empty:
        # Thrown if the CPO hook_execution logic fail
        raise InternalError("Cannot execute WCP prechecks")
    logger.info("WCP checks finished")
    return result
