"""Content Library Patch Logic for 6.6 minor releases

"""
import fileinput
import logging
import os
import pwd
import shutil

from patches.add_vmtx_privileges import add_privileges
from base import patch_info, patch_test
from patches.constants import (
    CONTENT_LIBRARY_CONFIG_HOME, CONTENT_LIBRARY_HOME, CONTENT_LIBRARY_SERVICE_SPEC,
    CONTENT_LIBRARY_SERVICE_REGISTER_SPEC, KEY_STORE_NAME_MACHINE,
    PATCH_VERSION_6_6_1, PATCH_VERSION_6_6_2, PATCH_VERSION_6_6_3, PATCH_VERSION_6_6_4,
    REVERSE_PROXY_ADDRESS_KEY, REVERSE_PROXY_CONNECTION_TYPE_KEY,
    REVERSE_PROXY_CONNECTION_TYPE_LOCAL, SOLUTION_USER_NAME_KEY, SOLUTION_USER_ID_KEY,
    TC_SERVER_DIR, CLOUDVM_COMPONENTS_FOR_ID_TRANSLATION, USER_ROOT, USER_VAPI_ENDPOINT, VAPI_ENDPOINT_PROPERTIES_FILE,
    VMTX_EXTENSION_PATH, VDC_PROPERTIES_FILE, VMTX_SERVICE_VAPI_CLI_JSON,
    VMTX_TEMPLATE_VAPI_COMPONENT)
from patches.messages import PATCH_SUMMARY_6_6_1, PATCH_SUMMARY_6_6_2, PATCH_SUMMARY_6_6_3, PATCH_SUMMARY_6_6_4
from utils import find_vdc_property, read_config


__author__ = 'VMware, Inc.'
__copyright__ = 'Copyright 2016-2017,2019 VMware, Inc. All rights reserved.'


logger = logging.getLogger(__name__)


@patch_info(PATCH_VERSION_6_6_1, PATCH_SUMMARY_6_6_1)
def patch_executor_6_6_1(patch_context):
    logger.info("Uninstalling tc Server")
    if os.path.exists(TC_SERVER_DIR):
        logger.info("Removing: %s", TC_SERVER_DIR)
        shutil.rmtree(TC_SERVER_DIR, True)


@patch_info(PATCH_VERSION_6_6_2, PATCH_SUMMARY_6_6_2)
def patch_executor_6_6_2(patch_context):
    """
    Add vmtx extension path property entry to vdc.properties if not there.
    """
    logger.info("Updating Vmtx extension path property")
    if not find_vdc_property(VMTX_EXTENSION_PATH):
        with open(VDC_PROPERTIES_FILE, "a") as fp:
            logger.info("Adding vdc property: %s", VMTX_EXTENSION_PATH)
            fp.write("\n" + VMTX_EXTENSION_PATH)


@patch_info(PATCH_VERSION_6_6_3, PATCH_SUMMARY_6_6_3)
def patch_executor_6_6_3(patch_context):
    """
    Register VMTX service with lookup service and update VMTX VAPI endpoint if not already.
    """
    register_vmtx_service()
    update_vmtx_vapi_component()


@patch_info(PATCH_VERSION_6_6_4, PATCH_SUMMARY_6_6_4)
def patch_executor_6_6_4(patch_context):
    """
    Register the additional privileges needed for VMTX Sync.
    """
    add_privileges()


def register_vmtx_service():
    """
    Register VMTX service with lookup service as a patch, which is a re-registration. The
    registration uses existing info from service registration spec and uses key store name "machine"
    for lookup service connection.
    """
    from cis_register import RegCIS

    logger.info("Read registered info from %s", CONTENT_LIBRARY_SERVICE_REGISTER_SPEC)
    service_register_properties = read_config(CONTENT_LIBRARY_SERVICE_REGISTER_SPEC)

    solution_user_name = None
    solution_user_id = None
    reverse_proxy_address = None
    for key, value in service_register_properties.items():
        if VMTX_SERVICE_VAPI_CLI_JSON in value:
            logger.info("VMTX service already registered, skip VMTX service registration.")
            return
        if key == SOLUTION_USER_NAME_KEY:
            solution_user_name = value
        elif key == SOLUTION_USER_ID_KEY:
            solution_user_id = value
        elif key == REVERSE_PROXY_ADDRESS_KEY:
            reverse_proxy_address = value
        elif key == REVERSE_PROXY_CONNECTION_TYPE_KEY:
            reverse_proxy_connection_type = value
            if reverse_proxy_connection_type != REVERSE_PROXY_CONNECTION_TYPE_LOCAL:
                raise Exception("proxy connection type should be local in a patch setup!")

    logger.info("Registering VMTX service with lookup service")
    logger.info("Using solution user name: %s, solution user id: %s, reverse proxy address: %s",
                solution_user_name, solution_user_id, reverse_proxy_address)

    # Note: This is a re-registration by specifying is_patch as true, and reverse proxy address for
    #       local connection is the port only
    vmtx_reg_info = RegCIS(CONTENT_LIBRARY_HOME, services_spec=CONTENT_LIBRARY_SERVICE_SPEC,
                           vdc_cfg_dir=CONTENT_LIBRARY_CONFIG_HOME,
                           service_http_port=reverse_proxy_address, is_patch=True,
                           key_store_name=KEY_STORE_NAME_MACHINE)
    vmtx_reg_info.registerAll(solution_user_name, solution_user_id)
    logger.info("Registered VMTX service successfully")


def update_vmtx_vapi_component():
    """
    This function ensures that the VMTX component is included in the list (if it is not
    already) of components for which ID translation is performed.
    Also ensure that endpoint property file ownership is restored after the update
    """
    logger.info("Updating VAPI endpoint properties if VMTX endpoint is not included yet")
    with fileinput.FileInput(VAPI_ENDPOINT_PROPERTIES_FILE, inplace=True) as file:
        for line in file:
            line = line.rstrip('\n')
            if line.startswith(CLOUDVM_COMPONENTS_FOR_ID_TRANSLATION + "="):
                if VMTX_TEMPLATE_VAPI_COMPONENT not in line:
                    logger.info("Adding VMTX API endpoint")
                    line = line + "," + VMTX_TEMPLATE_VAPI_COMPONENT
            # write back to file
            print(line)

    # restore endpoint property file ownership
    root_uid = pwd.getpwnam(USER_ROOT).pw_uid
    vapi_endpoint_uid = pwd.getpwnam(USER_VAPI_ENDPOINT).pw_uid
    os.chown(VAPI_ENDPOINT_PROPERTIES_FILE, vapi_endpoint_uid, root_uid)
    logger.info("Finished checking and updating VAPI endpoint properties")


@patch_test(PATCH_VERSION_6_6_1)
def patch_tester_6_6_1(patch_context):
    is_success = not os.path.exists(TC_SERVER_DIR)
    logger.info("Successfully uninstalled tc Server: %s", is_success)


@patch_test(PATCH_VERSION_6_6_2)
def patch_tester_6_6_2(patch_context):
    is_success = find_vdc_property(VMTX_EXTENSION_PATH)
    logger.info("VMTX extension path update status: %s", is_success)


@patch_test(PATCH_VERSION_6_6_3)
def patch_tester_6_6_3(patch_context):
    # verify VMTX service is registered
    vmtx_service_registered = False
    service_register_properties = read_config(CONTENT_LIBRARY_SERVICE_REGISTER_SPEC)
    for key, value in service_register_properties.items():
        if VMTX_SERVICE_VAPI_CLI_JSON in value:
            logger.info("Registered VMTX service successfully")
            vmtx_service_registered = True
            break
    if not vmtx_service_registered:
        error_message = "VMTX service is not registered properly!"
        logger.error(error_message)
        raise Exception(error_message)

    # verify VMTX API endpoint is configured
    vmtx_endpoint_updated = False
    vapi_properties = read_config(VAPI_ENDPOINT_PROPERTIES_FILE)
    for key, value in vapi_properties.items():
        if key == CLOUDVM_COMPONENTS_FOR_ID_TRANSLATION:
            vmtx_endpoint_updated = VMTX_TEMPLATE_VAPI_COMPONENT in value
    if not vmtx_endpoint_updated:
        error_message = "VMTX api endpoint is not configured with VAPI endpoints!"
        logger.error(error_message)
        raise Exception(error_message)
    logger.info("VMTX API endpoint is configured with VAPI endpoints properly.")
