import numpy as np

import SpectrumCommon.Const.GB.GBConst as gbc

import SpectrumCommon.Const.IS.ISConst as isc
import SpectrumCommon.Const.IS.ISConstLink as iscl
import SpectrumCommon.Const.IS.ISModVarFields as ismvf

#######################################################################################################
#                                                                                                     #
#                                       Facility type records                                         #
#                                                                                                     #
#######################################################################################################

#######################################################################################################
#                                                                                                     #
#                                       Facilities                                                    #
#                                                                                                     #
#######################################################################################################

def IS_create_facility_type_record(
    ID = str, name = str, string_const = str, active = bool, support_type_mst_ID = int, 
    deliv_chan_mst_ID = str, def_facility_type_map_mst_ID = int, num_years = int, costing_mode = int, plan_type = int, num_prog_areas = int
):

    facility_rec = {
        ismvf.IS_FACIL_TYPE_ID                                   : ID,
        ismvf.IS_FACIL_STR_CONSTANT                              : string_const,
        ismvf.IS_FACIL_NAME                                      : name,
        ismvf.IS_FACIL_ACTIVE                                    : active,
        ismvf.IS_FACIL_CUSTOM                                    : False,
        ismvf.IS_FACIL_SUPP_TYPE_MST_ID                          : support_type_mst_ID,
        ismvf.IS_FACIL_DELIV_CHAN_MST_ID                         : deliv_chan_mst_ID,
        ismvf.IS_FACIL_DEFAULT_MAP_MST_ID                        : def_facility_type_map_mst_ID,
        ismvf.IS_FACIL_TOTAL_NUMBER_BASELINE                     : 0,
        ismvf.IS_FACIL_AVG_NUM_BEDS                              : 0,
        ismvf.IS_FACIL_AVG_OCCUP_RATE_BEDS                       : 0,
        ismvf.IS_FACIL_AVG_NUM_OUTPAT_VISITS_PER_YEAR            : 0,
        ismvf.IS_FACIL_YEARS_TO_BUILD                            : 0,
        ismvf.IS_FACIL_TOTAL_CONSTRUCT_COST                      : 0,
        ismvf.IS_FACIL_LAND_COST                                 : 0.0,
        ismvf.IS_FACIL_CONSTRUCT_COST_PER_SQ_M                   : 0.0,
        ismvf.IS_FACIL_AVG_SIZE_IN_SQ_M                          : 0.0,
        ismvf.IS_FACIL_REHAB_COST                                : np.full((isc.IS_NUM_REHAB_TYPES), 0.0).tolist(),
        ismvf.IS_FACIL_TOTAL_OP_COST                             : 0.0,
        ismvf.IS_FACIL_TOTAL_OP_COSTS_PERC_CONSTRUCT_COST        : 0.0,
        ismvf.IS_FACIL_DESIRED_POP_FACIL_RATIO_POP_NORMS         : 0,
        ismvf.IS_FACIL_TARG_SCALE_UP_POP_NORMS                   : np.full((num_years), 0).tolist(),
        ismvf.IS_FACIL_TARG_SCALE_UP_EXIST_PLANS_EXPECTED_OP     : np.full((num_years), 0).tolist(),
        ismvf.IS_FACIL_TARG_SCALE_UP_EXIST_PLANS_BEGIN_CONSTRUCT : np.full((num_years), 0).tolist(),
        ismvf.IS_FACIL_TARG_NUM_TO_REHAB                         : np.full((isc.IS_NUM_REHAB_TYPES), 0.0).tolist(),
        ismvf.IS_FACIL_TARG_NUM_TO_REHAB_BY_YEAR                 : np.full((isc.IS_NUM_REHAB_TYPES, num_years), 0.0).tolist(),
    }

    # In IHT specific-plan mode, we need certain fields to vary by programme/health area
    if (costing_mode == gbc.GB_IHT_COSTING_MODE) and (plan_type == iscl.IS_IH_SPECIFIC_PLAN):
        facility_rec[ismvf.IS_FACIL_NUM_TO_EQUIP] = np.full((num_prog_areas, num_years), 0).tolist()
        facility_rec[ismvf.IS_FACIL_EQUIP_PURCHASE_COST] = np.full((num_prog_areas, isc.IS_NUM_FACIL_EQUIP_TYPES), 0.0).tolist()

    else: 
        facility_rec[ismvf.IS_FACIL_NUM_TO_EQUIP] = np.full((num_years), 0).tolist()
        facility_rec[ismvf.IS_FACIL_EQUIP_PURCHASE_COST] = np.full((isc.IS_NUM_FACIL_EQUIP_TYPES), 0.0).tolist()

    if costing_mode == gbc.GB_TB_COSTING_MODE:
        facility_rec[ismvf.IS_FACIL_MED_EQUIP_MAINT_COST] = 0
        facility_rec[ismvf.IS_FACIL_MED_EQUIP_CALIB_COST] = 0
    
    elif (costing_mode == gbc.GB_IHT_COSTING_MODE) and (plan_type == iscl.IS_IH_SPECIFIC_PLAN):
        facility_rec[ismvf.IS_FACIL_MED_EQUIP_MAINT_COST] = np.full((num_prog_areas), 0).tolist()
        facility_rec[ismvf.IS_FACIL_MED_EQUIP_CALIB_COST] = np.full((num_prog_areas), 0).tolist()

    return facility_rec

def IS_init_facility_type_records(num_years, costing_mode = int, plan_type = int, num_prog_areas = int):
    facility_type_records = []

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_HEALTH_POST_MST_ID), 
            'Health post', 
            'GB_stHealthPost', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_COMMUNITY_CHAN_MST_ID),
            isc.IS_HEALTH_POST_MST_ID,
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_PREHOSPITAL_EMERGENCY_MST_ID), 
            'Prehospital emergency', 
            'GB_stPrehospitalEmergency', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_PREHOSPITAL_EMERGENCY_CHAN_MST_ID),
            isc.IS_PREHOSPITAL_EMERGENCY_MST_ID,
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_HEALTH_CENTER_MST_ID), 
            'Health centre', 
            'GB_stHealthCentre', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_GEN_OUTPATIENT_SERV_CHAN_MST_ID),
            isc.IS_HEALTH_CENTER_MST_ID, 
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_FREE_STAND_GEN_OUTPAT_CLINIC_MST_ID), 
            'Free-standing general outpatient clinic', 
            'GB_stFreeStandingGenOutpatientClinic', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_GEN_OUTPATIENT_SERV_CHAN_MST_ID),
            isc.IS_FREE_STAND_GEN_OUTPAT_CLINIC_MST_ID,
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_DISTRICT_GEN_HOSPITAL_MST_ID), 
            'District/General hospital', 
            'GB_stDistrictGeneralHospital', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_FIRST_REFERRAL_CHAN_MST_ID),
            isc.IS_DISTRICT_GEN_HOSPITAL_MST_ID, 
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_NAT_REG_PROV_HOSPITAL_MST_ID), 
            'National/Regional/Provincial hospital', 
            'GB_stNatRegProvincialHospital', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_SEC_REFERRAL_CHAN_MST_ID),
            isc.IS_NAT_REG_PROV_HOSPITAL_MST_ID, 
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    facility_type_records.append(
        IS_create_facility_type_record(
            str(isc.IS_FREE_STAND_SPEC_OUTPAT_CLINIC_MST_ID), 
            'Free-standing specialized outpatient clinic', 
            'GB_stFreeStandingSpecOutpatientClinic', 
            True,
            isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
            str(iscl.IS_IH_SEC_REFERRAL_CHAN_MST_ID),
            isc.IS_FREE_STAND_SPEC_OUTPAT_CLINIC_MST_ID, 
            num_years,
            costing_mode,
            plan_type,
            num_prog_areas
        )
    )

    # facility_type_records.append(
    #     IS_create_facility_type_record(
    #         str(isc.IS_CENTRAL_HOSPITAL_MST_ID), 
    #         'Central Hospital', 
    #         'GB_stCentralHospital', 
    #         True,
    #         isc.IS_FACILITY_DELIV_INTERV_MST_ID, 
    #         str(iscl.IS_IH_FIRST_REFERRAL_CHAN_MST_ID),
    #         isc.IS_CENTRAL_HOSPITAL_MST_ID, 
    #         num_years,
    #        costing_mode  
    #     )
    # )

    return facility_type_records

def IS_create_vehicle_type_record(ID = str, name = str, num_facilities = int):

    return {
        ismvf.IS_VEHIC_ID                          : ID,
        ismvf.IS_VEHIC_NAME                        : name,
        ismvf.IS_VEHIC_CUSTOM                      : False,
        ismvf.IS_VEHIC_CURR_NUMBER                 : 0.0,
        ismvf.IS_VEHIC_UNIT_COST                   : 0.0,
        ismvf.IS_VEHIC_WORKING_LIFE_YEARS          : 5.0,
        ismvf.IS_VEHIC_DRIVER_SALARY               : 0.0,
        ismvf.IS_VEHIC_FUEL_CONSUMPTION            : 0.0,
        ismvf.IS_VEHIC_DISTANCE_DRIVEN_PER_YEAR    : 0.0,
        ismvf.IS_VEHIC_FUEL_COST_DIRECT_ENTRY      : 0.0,
        ismvf.IS_VEHIC_REPAIR_MAINT_PERC_CAP_COST  : 0.0,
        ismvf.IS_VEHIC_TARG_NUM_PER_FACILITY       : np.full((num_facilities), 0).tolist(),
        ismvf.IS_VEHIC_TARG_NUM_PER_FACILITY_OTHER : 0,
    }

def IS_create_ICT_equip_type_record(ID = str, name = str, num_facilities = int):

    return {
        ismvf.IS_ICT_EQUIP_ID                      : ID,
        ismvf.IS_ICT_EQUIP_NAME                    : name,
        ismvf.IS_ICT_EQUIP_CUSTOM                  : False,
        ismvf.IS_ICT_EQUIP_CURR_NUMBER             : 0.0,
        ismvf.IS_ICT_EQUIP_UNIT_COST               : 0.0,
        ismvf.IS_ICT_EQUIP_WORKING_LIFE_YEARS      : 0.0,
        ismvf.IS_ICT_EQUIP_OP_COST_PERC_CAP_COST   : 0.0,
        ismvf.IS_ICT_REPAIR_MAINT_PERC_CAP_COST    : 0.0,
        ismvf.IS_ICT_TARG_NUM_PER_FACILITY         : np.full((num_facilities), 0).tolist(),
        ismvf.IS_ICT_TARG_NUM_PER_FACILITY_OTHER   : 0,
    }

def IS_create_facility_MEG_record(ID = str, name = str, facility_type_ID = str):

    return {
        ismvf.IS_FACIL_MEG_ID            : ID,
        ismvf.IS_FACIL_MEG_NAME          : name,
        ismvf.IS_FACIL_EQUIP_STR_CONST   : '',
        ismvf.IS_FACIL_MEG_FACIL_TYPE_ID : facility_type_ID,
    }

# Use for both facility medical equipment, which goes by group, and furniture, which does not. They currently have the same fields, but if that
# ceases to be the case, copy what's happening with the three types of treatment inputs in Intervention Costing
def IS_create_facility_equip_record(ID = str, name = str, facility_type_ID = str, facility_equip_type_mst_ID = int, costing_mode = int, IHT_plan_type = int):
    
    equip_record = {
        ismvf.IS_FACIL_EQUIP_ID            : ID, 
        ismvf.IS_FACIL_EQUIP_CUSTOM        : False,
        ismvf.IS_FACIL_EQUIP_NAME          : name,
        ismvf.IS_FACIL_MEG_STR_CONST       : '',
        ismvf.IS_FACIL_EQUIP_FACIL_TYPE_ID : facility_type_ID,        
        ismvf.IS_FACIL_EQUIP_UNIT_COST     : 0.0,
        ismvf.IS_FACIL_EQUIP_NUM_UNITS     : 0.0,
        ismvf.IS_FACIL_EQUIP_WORKING_LIFE  : 5.0,
    }

    # Only add this field for medical equipment. Irrelevant for furniture. 
    if facility_equip_type_mst_ID == isc.IS_FACIL_MEDICAL_EQUIP_MST_ID:
        equip_record[ismvf.IS_FACIL_EQUIP_MEG_ID] = "0"

        if (costing_mode == gbc.GB_TB_COSTING_MODE) or ((costing_mode == gbc.GB_IHT_COSTING_MODE) and (IHT_plan_type == iscl.IS_IH_SPECIFIC_PLAN)):
            equip_record[ismvf.IS_FACIL_EQUIP_MAINT_COST] = 0
            equip_record[ismvf.IS_FACIL_EQUIP_CALIB_COST] = 0

    return equip_record

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

def IS_init_facility_year_arr(num_facility_types = int, num_years = int, value = 0.0):
    return np.full((num_facility_types, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def IS_init_facility_prog_area_year_arr(num_facility_types = int, num_prog_areas = int, num_years = int, value = 0.0):
    return np.full((num_facility_types, num_prog_areas, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def IS_init_vehicle_year_arr(num_vehicle_types = int, num_years = int, value = 0.0):
    return np.full((num_vehicle_types, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def IS_init_vehicle_facility_year_arr(num_vehicle_types = int, num_facility_types = int, num_years = int, value = 0.0):
    return np.full((num_vehicle_types, num_facility_types, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def IS_init_ICT_year_arr(num_ICT_types = int, num_years = int, value = 0.0):
    return np.full((num_ICT_types, num_years), value, gbc.GB_CALC_FLOAT_TYPE)

def IS_init_ICT_facility_year_arr(num_ICT_types = int, num_facility_types = int, num_years = int, value = 0.0):
    return np.full((num_ICT_types, num_facility_types, num_years), value, gbc.GB_CALC_FLOAT_TYPE)
