#!/usr/bin/env python
# Copyright 2016-2020 VMware, Inc.
# All rights reserved. -- VMware Confidential

import logging
import os
import json
import update_utils

logger = logging.getLogger(__name__)

GATEWAY_PRODUCT_CONF = '/etc/vmware/products.conf'
INSTALLED_INDICATOR = "installed"
FB_STATUS_FILE = '/var/log/firstboot/fbInstall.json'
HLM_FSS_FILE = '/usr/lib/vmware/site-packages/featureState.py'
PLATFORM_FSS_FILE = '/usr/lib/vmware-vmcg/site-packages/featureState.py'

def _getProductConfiguration():
    ''' Returns the information about installed products.

    @return: Dict representing information of installed products.
    If it is not present returns None
    @rtype: dict or None if not present
    {
        "HLM" : {
            "installed": true
        }
    }
    '''
    if not os.path.isfile(GATEWAY_PRODUCT_CONF):
        # Once the FSS is enabled then file absence should be
        # treated as error, by the time FSS is enabled
        # all gateways should have product configuration
        # file created via vmc_gateway patch
        if update_utils.getSourceFSS('GW_PLATFORM_UPDATE'):
            raise Exception('Product configuration file does not exists')
        logger.warn("Product configuration file does not exists.")
        return None
    with open(GATEWAY_PRODUCT_CONF) as fp:
        return json.load(fp)


def getAllProducts():
    '''
    Get all products from services.json
    :return: set of products
    '''
    with open(update_utils.SERVICES_JSON) as f:
        servicesJson = json.load(f)

    allProducts = []
    for service in servicesJson.values():
        if service.get("products", None):
            allProducts.extend(service.get("products"))
    return set(allProducts)


def isProductEnabled(product):
    '''
    Check if the given product is installed/enabled
    :param product:
    :return: True or False based on whether product in installed/enabled
    '''
    logger.debug("Checking if product %s is enabled", product)
    confContent = _getProductConfiguration()

    # To support old gateways that don't have product configuration file
    if confContent is None:
        return True

    productEnabled = confContent.get(product, {}) \
                            .get(INSTALLED_INDICATOR, False)
    logger.debug("Product %s install status %s", product, productEnabled)
    return productEnabled


def getUpdateProduct():
    '''
    Gets the name of the product being updated based on the update manifest and
    product installation status, returns None if its gateway platform update.
    Raises error if product update is triggered when product is not installed.
    :return: name of product
    '''
    if not update_utils.isGateway():
        return None
    manifestJson = update_utils.get_rpm_manifest()
    logger.debug("Checking if its product update")
    product = manifestJson['header'].get('productname', None)
    if product and \
            not 'VMware-vCenter-Cloud-Gateway'.lower() in product.lower():
        if isProductEnabled(product):
            logger.debug("%s product update" % product)
            return product
        logger.debug("Product %s not installed, update not allowed", product)
        raise Exception('Product not installed, product update not allowed')
    logger.debug("Not a product update, will perform platform update")
    return None


def isHlmInstalled():
    '''
    Indicate if HLM is installed on this gateway
    :return: return True is HLM is installed on this gateway else False
    '''
    logger.info('Checking if HLM is installed')
    productEnabled = False
    if os.path.exists(FB_STATUS_FILE):
        with open(FB_STATUS_FILE) as fp:
            content = json.load(fp)
        if 'success' in content.get('status', None):
            productEnabled = True
            logger.info('HLM is installed')
    return productEnabled


def isHlmUpdate():
    '''
    Indicate if HLM update
    :return: return True is HLM is being updated
    '''
    update_product = getUpdateProduct()
    if isHlmInstalled() and update_product and \
            (update_product.lower() == 'hlm'
             or update_product.lower() == 'hybrid linked mode'):
        return True
    return False
