# Contains methods for setting up more complicated IHT ModVars; others can just be set up in ICModVars.py

import numpy as np

import SpectrumCommon.Const.GB.GBConst as gbc

import SpectrumCommon.Const.BG.BGConst as bgc
import SpectrumCommon.Const.BG.BGConstLink as bgcl
import SpectrumCommon.Const.BG.BGModVarFields as bgmvf

#######################################################################################################
#                                                                                                     #
#                                       Budgets                                                       #
#                                                                                                     #
#######################################################################################################

def BG_create_budget_rec(ID: str, name: str, string_constant: str, num_dynamic_staff_types: int):

    budget_rec = {
        bgmvf.BG_BUDGET_ID                                           : ID,                                                
        bgmvf.BG_BUDGET_NAME                                         : name,     
        bgmvf.BG_BUDGET_STR_CONST                                    : string_constant,             
        bgmvf.BG_BUDGET_COST_INTERVS_DRUGS_SUPPLIES_IC               : bgc.BG_IC_COST_INTERVENTIONS_MST_ID,
        bgmvf.BG_BUDGET_AGGR_DELIV_CHANS_IC                          : True,
        bgmvf.BG_BUDGET_CUSTOM                                       : False,
        bgmvf.BG_BUDGET_ACTIVE                                       : True,
        bgmvf.BG_BUDGET_FW_ID                                        : '-1',

        bgmvf.BG_COST_CAT_IC_ID                                      : bgc.BG_IC_DRUGS_SUPPLIES_CC_MST_ID,

        bgmvf.BG_BUDGET_COST_LEVEL_PC_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,
        bgmvf.BG_BUDGET_COST_LEVEL_IS_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,
        bgmvf.BG_BUDGET_COST_LEVEL_HW_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,

        bgmvf.BG_BUDGET_AGGR_INSERV_TRAIN_ALL_STAFF_HW               : False,
        bgmvf.BG_BUDGET_AGGR_PRESERV_TRAIN_ALL_STAFF_HW              : False, 
        bgmvf.BG_BUDGET_AGGR_TOTAL_COMPENS_ALL_STAFF_HW              : np.full((bgcl.BG_HW_NUM_STAFFING_LEVELS, bgcl.BG_HW_NUM_COMPENS_TYPES), False).tolist(),
        bgmvf.BG_BUDGET_AGGR_STAFF_INSERV_TRAIN_ALL_STAFF_LEV_HW     : np.full((num_dynamic_staff_types), False).tolist(),
        bgmvf.BG_BUDGET_AGGR_STAFF_LEV_INSERV_TRAIN_ALL_STAFF_HW     : np.full((bgcl.BG_HW_NUM_STAFFING_LEVELS), False).tolist(),
        bgmvf.BG_BUDGET_AGGR_TOTAL_COMPENS_STAFF_LEV_COMPENS_TYPE_HW : np.full((num_dynamic_staff_types), False).tolist(),

        bgmvf.BG_BUDGET_GROUP_IND_AGGR_SET_IS                        : [],
        bgmvf.BG_BUDGET_FACILITY_IND_AGGR_SET_IS                     : [],

        bgmvf.BG_BUDGET_COST_LEVEL_HS_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,
        bgmvf.BG_BUDGET_COST_LEVEL_GV_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,
        bgmvf.BG_BUDGET_COST_LEVEL_HF_ID                             : bgc.BG_COST_COSTING_SECTIONS_LEVEL_MST_ID,
    }

    return budget_rec

#######################################################################################################
#                                                                                                     #
#                                       Budget categories                                             #
#                                                                                                     #
#######################################################################################################

def BG_create_budget_category_rec(budget_ID = str, budget_cat_ID = str, name = str, string_constant = str, num_years = int):
    
    budget_cat_rec = {
        bgmvf.BG_BUDGET_CAT_BUDGET_ID                  : budget_ID,
        bgmvf.BG_BUDGET_CAT_ID                         : budget_cat_ID,
        bgmvf.BG_BUDGET_CAT_NAME                       : name,         
        bgmvf.BG_BUDGET_CAT_STR_CONST                  : string_constant,              
        bgmvf.BG_BUDGET_CAT_TOTAL_COST                 : np.full((num_years), 0.0).tolist(),
        bgmvf.BG_BUDGET_CAT_CUSTOM                     : False,
    }

    return budget_cat_rec

#######################################################################################################
#                                                                                                     #
#                                       Budget category shares                                        #
#                                                                                                     #
#######################################################################################################

def BG_create_budget_category_share_rec_PC(budget_ID = str, ind_type_ID = int, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_PC, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID)

    # For clarity, use theses three and never the indID field for PC indicators
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # If IHT, then the PC indicators will vary by programme area as well.
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_HS(budget_ID = str, ind_type_ID = int, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_HS, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_GV(budget_ID = str, ind_type_ID = int, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_GV, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_HF(budget_ID = str, ind_type_ID = int, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_HF, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_IC(budget_ID = str, ind_type_ID = int, ind_ID = str, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_IC, ind_type_ID, ind_ID, budget_cat_ID)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_DELIV_CHAN_ID] = str(gbc.GB_NOT_FOUND)

    # In IHT specific-plan mode, logistics and supply chain costs and wastage costs can be mapped by prog area. Otherwise, this field is not applicable.
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_HW(budget_ID = str, ind_type_ID = int, ind_ID = str, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_HW, ind_type_ID, ind_ID, budget_cat_ID)

    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_STAFF_LEVEL_ID_HW] = str(gbc.GB_NOT_FOUND) # equivalent to all staffing levels
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COMPENS_TYPE_ID_HW] = str(gbc.GB_NOT_FOUND) # equivalent to all compensation types

    # For programme management indicators, use these instead of ind_ID, staff_level_ID, and compens_type_ID. Pass in str(gbc.GB_NOT_FOUND) 
    # for ind_ID on creation. 
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec_IS(budget_ID = str, ind_type_ID = int, ind_ID = str, budget_cat_ID = str):
    budget_cat_share_rec = BG_create_budget_category_share_rec(budget_ID, gbc.GB_IS, ind_type_ID, ind_ID, budget_cat_ID)

    # For programme management indicators, use these instead of ind_ID. Most IS indicators vary by facility type, so we have an ind_ID param.
    # If it's a programme management indicator, just pass str(gbc.GB_NOT_FOUND) for ind_ID on creation and set these fields appropriately after.
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # In IHT specific-plan mode, medical equipment and medical equipment maintenance and calibration costs can be mapped by prog area. Otherwise, this field is not applicable.
    budget_cat_share_rec[bgmvf.BG_BUDGET_CAT_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return budget_cat_share_rec

def BG_create_budget_category_share_rec(budget_ID = str, mod_ID = int, ind_type_ID = int, ind_ID = str, budget_cat_ID = str):
    
    budget_cat_share_rec = {
        bgmvf.BG_BUDGET_CAT_SHARE_BUDGET_ID     : budget_ID,
        bgmvf.BG_BUDGET_CAT_SHARE_MOD_ID        : mod_ID,
        bgmvf.BG_BUDGET_CAT_SHARE_IND_TYPE_ID   : ind_type_ID, 
        bgmvf.BG_BUDGET_CAT_SHARE_IND_ID        : ind_ID,
        bgmvf.BG_BUDGET_CAT_SHARE_BUDGET_CAT_ID : budget_cat_ID,
        bgmvf.BG_BUDGET_CAT_SHARE_VALUE         : 0.0,
    }

    return budget_cat_share_rec

#######################################################################################################
#                                                                                                     #
#                                       Funding frameworks                                            #
#                                                                                                     #
#######################################################################################################

def BG_create_funding_framework_rec(ID = str, name = str, string_constant = str):

    funding_framework_rec = {
        bgmvf.BG_FUND_FW_ID           : ID,                          
        bgmvf.BG_FUND_FW_NAME         : name,   
        bgmvf.BG_FUND_FW_STR_CONSTANT : string_constant,  
        bgmvf.BG_FUND_FW_CUSTOM       : False,                
    }

    return funding_framework_rec

#######################################################################################################
#                                                                                                     #
#                                       Funding sources                                               #
#                                                                                                     #
#######################################################################################################

def BG_create_funding_source_rec(fund_framework_ID = str, fund_source_ID = str, name = str, string_constant = str):
    
    funding_source_rec = {
        bgmvf.BG_FUND_SOURCE_FW_ID        : fund_framework_ID,
        bgmvf.BG_FUND_SOURCE_ID           : fund_source_ID,
        bgmvf.BG_FUND_SOURCE_NAME         : name,     
        bgmvf.BG_FUND_SOURCE_STR_CONSTANT : string_constant,     
        bgmvf.BG_FUND_SOURCE_CUSTOM       : False,             
    }

    return funding_source_rec

#######################################################################################################
#                                                                                                     #
#                                       Funding source shares                                         #
#                                                                                                     #
#######################################################################################################

def BG_create_funding_source_share_rec_PC(budget_ID = str, ind_type_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_PC, ind_type_ID, str(gbc.GB_NOT_FOUND), fund_framework_ID, fund_source_ID)

    # For clarity, use theses three and never the indID field for PC indicators
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # If IHT, then the PC indicators will vary by programme area as well.
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_HS(budget_ID = str, ind_type_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_HS, ind_type_ID, str(gbc.GB_NOT_FOUND), fund_framework_ID, fund_source_ID)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_GV(budget_ID = str, ind_type_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_GV, ind_type_ID, str(gbc.GB_NOT_FOUND), fund_framework_ID, fund_source_ID)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_HF(budget_ID = str, ind_type_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_HF, ind_type_ID, str(gbc.GB_NOT_FOUND), fund_framework_ID, fund_source_ID)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_IC(budget_ID = str, ind_type_ID = int, ind_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_IC, ind_type_ID, ind_ID, fund_framework_ID, fund_source_ID)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_DELIV_CHAN_ID] = str(gbc.GB_NOT_FOUND)

    # In IHT specific-plan mode, logistics and supply chain costs and wastage costs can be mapped by prog area. Otherwise, this field is not applicable.
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_HW(budget_ID = str, ind_type_ID = int, ind_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_HW, ind_type_ID, ind_ID, fund_framework_ID, fund_source_ID)

    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_STAFF_LEVEL_ID_HW] = str(gbc.GB_NOT_FOUND) # equivalent to all staffing levels
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COMPENS_TYPE_ID_HW] = str(gbc.GB_NOT_FOUND) # equivalent to all compensation types

    # For programme management indicators, use these instead of ind_ID, staff_level_ID, and compens_type_ID. Pass in str(gbc.GB_NOT_FOUND) 
    # for ind_ID on creation. 
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec_IS(budget_ID = str, ind_type_ID = int, ind_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = BG_create_funding_source_share_rec(budget_ID, gbc.GB_IS, ind_type_ID, ind_ID, fund_framework_ID, fund_source_ID)

    # For programme management indicators, use these instead of ind_ID. Most IS indicators vary by facility type, so we have an ind_ID param.
    # If it's a programme management indicator, just pass str(gbc.GB_NOT_FOUND) for ind_ID on creation and set these fields appropriately after.
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # In IHT specific-plan mode, medical equipment and medical equipment maintenance and calibration costs can be mapped by prog area. Otherwise, this field is not applicable.
    funding_source_share_rec[bgmvf.BG_FUND_SOURCE_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return funding_source_share_rec

def BG_create_funding_source_share_rec(budget_ID = str, mod_ID = int, ind_type_ID = int, ind_ID = int, fund_framework_ID = str, fund_source_ID = str):
    
    funding_source_share_rec = {
        bgmvf.BG_FUND_SOURCE_SHARE_BUDGET_ID      : budget_ID,
        bgmvf.BG_FUND_SOURCE_SHARE_MOD_ID         : mod_ID,
        bgmvf.BG_FUND_SOURCE_SHARE_IND_TYPE_ID    : ind_type_ID, 
        bgmvf.BG_FUND_SOURCE_SHARE_IND_ID         : ind_ID,
        bgmvf.BG_FUND_SOURCE_SHARE_FW_ID          : fund_framework_ID,
        bgmvf.BG_FUND_SOURCE_SHARE_FUND_SOURCE_ID : fund_source_ID,
        bgmvf.BG_FUND_SOURCE_SHARE_VALUE          : 0.0,
    }

    return funding_source_share_rec

#######################################################################################################
#                                                                                                     #
#                                       Indicators                                                    #
#                                                                                                     #
#######################################################################################################

def BG_create_indicator_rec_PC(budget_ID = str, ind_type_ID = int, budget_cat_ID = str, name = str):
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_PC, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID, name)

    # For clarity, use theses three and never the indID field for PC indicators
    ind_rec[bgmvf.BG_IND_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # If IHT, then the PC indicators will vary by programme area as well.
    ind_rec[bgmvf.BG_IH_F_PROG_AREA_ID] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_HS(budget_ID = str, ind_type_ID = int, budget_cat_ID = str, name = str):
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_HS, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID, name)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_HS_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_HS_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_GV(budget_ID = str, ind_type_ID = int, budget_cat_ID = str, name = str):
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_GV, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID, name)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_GV_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_GV_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_HF(budget_ID = str, ind_type_ID = int, budget_cat_ID = str, name = str):
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_HF, ind_type_ID, str(gbc.GB_NOT_FOUND), budget_cat_ID, name)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_HF_COSTING_ID] = str(gbc.GB_NOT_FOUND)

    ind_rec[bgmvf.BG_IND_COSTING_SECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_HF_PROG_MGMT_ID] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_IC(budget_ID = str, ind_type_ID = int, ind_ID = int, budget_cat_ID = str, name = str):
    # ind_ID should be an intervention or drug/supply ID.
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_IC, ind_type_ID, ind_ID, budget_cat_ID, name)

    ind_rec[bgmvf.BG_IND_DELIV_CHAN_ID_IC] = str(gbc.GB_NOT_FOUND) # equivalent to all delivery channels (OR none for indicators where delivery channel is irrelevant)

    # In IHT specific-plan mode, logistics and supply chain costs and wastage costs can be mapped by prog area. Otherwise, this field is not applicable.
    ind_rec[bgmvf.BG_IND_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_HW(budget_ID = str, ind_type_ID = int, ind_ID = int, budget_cat_ID = str, name = str):
    # ind_ID should be a staff type ID.
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_HW, ind_type_ID, ind_ID, budget_cat_ID, name)

    ind_rec[bgmvf.BG_IND_STAFF_LEVEL_ID_HW] = gbc.GB_NOT_FOUND # equivalent to all staffing levels
    ind_rec[bgmvf.BG_IND_COMPENS_TYPE_ID_HW] = gbc.GB_NOT_FOUND # equivalent to all compensation types

    # For programme management indicators, use these instead of ind_ID, staff_level_ID, and compens_type_ID. Pass in str(gbc.GB_NOT_FOUND) 
    # for ind_ID on creation. 
    ind_rec[bgmvf.BG_IND_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec_IS(budget_ID = str, ind_type_ID = int, ind_ID = int, budget_cat_ID = str, name = str):
    # ind_ID should be a facility type ID.
    ind_rec = BG_create_indicator_rec(budget_ID, gbc.GB_IS, ind_type_ID, ind_ID, budget_cat_ID, name)

    # For programme management indicators, use these instead of ind_ID. Most IS indicators vary by facility type, so we have an ind_ID param.
    # If it's a programme management indicator, just pass str(gbc.GB_NOT_FOUND) for ind_ID on creation and set these fields appropriately after.
    ind_rec[bgmvf.BG_IND_COSTING_SECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_COSTING_SUBSECT_ID_PC] = str(gbc.GB_NOT_FOUND)
    ind_rec[bgmvf.BG_IND_ACT_ID_PC] = str(gbc.GB_NOT_FOUND)

    # In IHT specific-plan mode, medical equipment and medical equipment maintenance and calibration costs can be mapped by prog area. Otherwise, this field is not applicable.
    ind_rec[bgmvf.BG_FUND_SOURCE_SHARE_PROG_AREA_ID_PC] = str(gbc.GB_NOT_FOUND)

    return ind_rec

def BG_create_indicator_rec(budget_ID = str, mod_ID = int, ind_type_ID = int, ind_ID = int, budget_cat_ID = str, name = str):
    
    ind_rec = {
        bgmvf.BG_IND_BUDGET_ID                  : budget_ID,
        # bgmvf.BG_IND_FUND_FW_ID                 : fund_framework_ID, 
        bgmvf.BG_IND_MOD_ID                     : mod_ID,
        bgmvf.BG_IND_TYPE_ID                    : ind_type_ID,
        bgmvf.BG_IND_ID                         : ind_ID,
        bgmvf.BG_IND_BUDGET_CAT_ID              : budget_cat_ID,
        # bgmvf.BG_IND_FUND_SOURCE_ID             : fund_source_ID, 
        bgmvf.BG_IND_NAME                       : name,
        #bgmvf.BG_IND_IS_AGGREGATE               : False, # stopped using this in favor of using str(gbc.GB_NOT_FOUND) as the indicator ID for all items combined.                                                                                                                                                                                               
        #bgmvf.BG_IND_DISTRIB_MULTI_CATS         : False,
        #bgmvf.BG_IND_DISTRIB_MULTI_FUND_SOURCES : False,
        bgmvf.BG_IND_FUND_SOURCE_BY_FRAMEWORK   : {},
    }

    return ind_rec

#######################################################################################################
#                                                                                                     #
#                                            Quick mapping                                            #
#                                                                                                     #
#######################################################################################################

def BG_create_quick_map_rec(budget_ID = str, mod_ID = int, target_ID = int, ind_type_ID = int):
    
    quick_map_rec = {
        bgmvf.BG_QUICK_MAP_BUDGET_ID      : budget_ID,
        bgmvf.BG_QUICK_MAP_MOD_ID         : mod_ID,
        bgmvf.BG_QUICK_MAP_TARGET_ID      : target_ID,
        bgmvf.BG_QUICK_MAP_IND_TYPE_ID    : ind_type_ID,
        bgmvf.BG_QUICK_MAP_IS_AGGREGATE   : False,        
        bgmvf.BG_QUICK_MAP_ON             : False,                                                                                                                                                                                                
    }

    # if mod_ID == gbc.GB_IC:
    #     quick_map_rec[bgmvf.BG_QUICK_MAP_DELIV_CHAN_ID_IC] = gbc.GB_NOT_FOUND

    return quick_map_rec

#######################################################################################################
#                                                                                                     #
#                                            Results                                                  #
#                                                                                                     #
#######################################################################################################

def BG_init_budget_cat_year_arr(num_budgets = int, num_budget_cats = int, num_years = int, value = 0.0):
     return np.full((num_budgets, num_budget_cats, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def BG_init_budget_fund_source_year_arr(num_budgets = int, num_fund_frameworks = int, num_funding_sources = int, num_years = int, value = 0.0):
     return np.full((num_budgets, num_fund_frameworks, num_funding_sources, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def BG_init_budget_cat_fund_source_res_rec(budget_ID = str, fund_framework_ID = str, fund_source_ID = str, budget_cat_ID = str, num_years = int):
    return {
        bgmvf.BG_BUDGET_ID      : budget_ID,
        bgmvf.BG_FUND_FW_ID     : fund_framework_ID,
        bgmvf.BG_FUND_SOURCE_ID : fund_source_ID,
        bgmvf.BG_BUDGET_CAT_ID  : budget_cat_ID,
        bgmvf.BG_F_VALUE        : np.full((num_years), 0.0, gbc.GB_CALC_FLOAT_TYPE)
    }