from datetime import date
import numpy as np
from copy import deepcopy

import AvenirCommon.Util as acu

import SpectrumCommon.Const.GB.GBConst as gbc
import SpectrumCommon.Const.PJ.PJNTags as pjmvt
import SpectrumCommon.Modvars.GB.GBUtil as gbu

import SpectrumCommon.Const.IS.ISConst as isc
import SpectrumCommon.Const.IS.ISTags as ismvt
import SpectrumCommon.Modvars.IS.ISModVarDefs as ismvd
import SpectrumCommon.Modvars.IS.ISReadDatabases as isrd
import SpectrumCommon.Modvars.IS.ISModVarDefsLink as ismvdl
import SpectrumCommon.Modvars.IS.ISModVarUtil as ismvu
import SpectrumCommon.Util.IS.ISTransactionCalcUtil as istcu
import SpectrumCommon.Const.IS.ISConstLink as iscl
import SpectrumCommon.Util.IS.ISUtilLink as isul

def init_modvars(countryID, first_year, final_year, extra):
    '''
        Initializes Infrastructure MVs for new IHT projections.

            Parameters:
                countryID (string):  Ex: BEN for Benin.

                first_year (int): First year selected by user.

                final_year (int): Final year selected by user. 

                extra (dict): Any other fields.  
 
            Returns:
                mod_vars_rec (dict): MVs.
    '''

    prog_area_records_mv = extra[iscl.IS_IH_PROG_AREA_RECORDS_TAG_V1]
    IHT_costing_on = extra[gbc.GB_IHT_ON] if gbc.GB_IHT_ON in extra else False
    TB_costing_on = extra[gbc.GB_TB_COSTING_ON] if gbc.GB_TB_COSTING_ON in extra else False
    LiST_costing_on = extra[gbc.GB_LIST_COSTING_ON] if gbc.GB_LIST_COSTING_ON in extra else False
    plan_type = extra[gbc.GB_Extra_plantype] if gbc.GB_Extra_plantype in extra else iscl.IS_IH_COMPREHENSIVE_PLAN

    # Load databases
    facility_med_equip_group_DB = isrd.IS_load_facility_med_equip_group_DB()
    facility_equip_input_DB = isrd.IS_load_facility_equip_input_DB()

    value_bool_false = False
    value_bool_true = True

    value_int = 0
    value_flt = 0.0
    value_str = ''
    value_date = date.today().strftime("%B %d, %Y"),   

    num_years_inputs = final_year - first_year  + 1
    num_years_outputs = final_year - first_year + 1

    costing_mode = gbu.get_costing_mode({
        pjmvt.GB_IHTOnTag       : IHT_costing_on,
        pjmvt.GB_TBCostingOnTag : TB_costing_on,
        pjmvt.GB_LCOnTag        : LiST_costing_on,
    })

    num_prog_areas = isul.IS_get_IH_num_prog_areas(prog_area_records_mv)

    facility_type_records = ismvd.IS_init_facility_type_records(num_years_inputs, costing_mode, plan_type, num_prog_areas)

    facility_MEG_records = np.array(isrd.IS_init_facility_MEG_records(facility_med_equip_group_DB, TB_costing_on))

    # If we're doing IHT specific plan mode, the MEG records must vary by programme area.
    if IHT_costing_on and (plan_type == iscl.IS_IH_SPECIFIC_PLAN):
        facility_MEG_records_by_prog_area = np.empty((num_prog_areas), dtype=object)

        for i in acu.GBRange(1, num_prog_areas):
            facility_MEG_records_by_prog_area[i - 1] = deepcopy(facility_MEG_records).tolist()

        facility_MEG_records = facility_MEG_records_by_prog_area

    facility_MEG_records = facility_MEG_records.tolist()

    facility_med_equip_records, facility_furniture_records = isrd.IS_init_facility_equip_records(facility_equip_input_DB, costing_mode, plan_type)

    facility_med_equip_records = np.array(facility_med_equip_records)

    # If we're doing IHT specific plan mode, the facility medical equipment (not surprisingly) must also vary by programme area.
    if IHT_costing_on and (plan_type == iscl.IS_IH_SPECIFIC_PLAN):
        facility_med_equip_records_by_prog_area = np.empty((num_prog_areas), dtype=object)

        for i in acu.GBRange(1, num_prog_areas):
            facility_med_equip_records_by_prog_area[i - 1] = deepcopy(facility_med_equip_records).tolist()

        facility_med_equip_records = facility_med_equip_records_by_prog_area

    facility_med_equip_records = facility_med_equip_records.tolist()

    num_facility_types = ismvu.get_IS_num_facility_types(facility_type_records)

    facility_target_setting_method = isc.IS_TSFM_POP_NORMS_MST_ID

    ###################################################################################################################
    # 
    #                                             For testing calculations
    #
    ###################################################################################################################
    # for ft, facility_type_rec in enumerate(facility_type_records):
    #     ismvu.set_IS_facility_type_num_baseline(facility_type_rec, (ft + 1) * 1000)
    #     ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, ft + 1)
    #     ismvu.set_IS_facility_type_total_construction_cost(facility_type_rec, (ft + 1) * 1000000)
    #     ismvu.set_IS_facility_type_total_equip_cost(facility_type_rec, isc.IS_FACIL_MEDICAL_EQUIP_CURR_ID, (ft + 1) * 5000)
    #     ismvu.set_IS_facility_type_total_equip_cost(facility_type_rec, isc.IS_FACIL_FURNITURE_EQUIP_CURR_ID, (ft + 1) * 10000)
    #     ismvu.set_IS_facility_type_desired_pop_facility_ratio(facility_type_rec, 125000)

    #     for year in acu.GBRange(first_year, final_year):
    #         t_i = gbu.getYearIdx(year, first_year)
    #         ismvu.set_IS_facility_type_scale_up_pop_norms(facility_type_rec, t_i, (ft + 1) * 1000)

    # facility_type_rec = ismvu.get_IS_facility_type_rec_from_curr_ID(facility_type_records, 1)
    # ismvu.set_IS_facility_type_num_baseline(facility_type_rec, 500)
    # ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, 0)

    # facility_type_rec = ismvu.get_IS_facility_type_rec_from_curr_ID(facility_type_records, 2)
    # ismvu.set_IS_facility_type_num_baseline(facility_type_rec, 100)
    # ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, 1)

    # facility_type_rec = ismvu.get_IS_facility_type_rec_from_curr_ID(facility_type_records, 3)
    # ismvu.set_IS_facility_type_num_baseline(facility_type_rec, 10)
    # ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, 2)

    # facility_type_rec = ismvu.get_IS_facility_type_rec_from_curr_ID(facility_type_records, 4)
    # ismvu.set_IS_facility_type_num_baseline(facility_type_rec, 5)
    # ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, 3)

    # facility_type_rec = ismvu.get_IS_facility_type_rec_from_curr_ID(facility_type_records, 5)
    # ismvu.set_IS_facility_type_num_baseline(facility_type_rec, 1)
    # ismvu.set_IS_facility_type_num_years_to_build(facility_type_rec, 3)

    if plan_type == iscl.IS_IH_SPECIFIC_PLAN:
        calc_total_med_equip_costs_value = np.full((num_prog_areas), value_bool_false).tolist()
        calc_maint_costs_as_perc_med_equip_costs_value = np.full((num_prog_areas), value_bool_false).tolist()

    else:
        calc_total_med_equip_costs_value = value_bool_false # Enter directly is default
        calc_maint_costs_as_perc_med_equip_costs_value = value_bool_false

    if TB_costing_on or (IHT_costing_on and (plan_type == iscl.IS_IH_SPECIFIC_PLAN)):
        mod_vars_dict = {
            ismvt.IS_FACILITY_TYPE_RECORDS_TAG                    : facility_type_records,
            ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG               : facility_med_equip_records,
            ismvt.IS_CALC_MAINT_COSTS_AS_PERC_MED_EQUIP_COSTS_TAG : calc_maint_costs_as_perc_med_equip_costs_value,
            pjmvt.GB_TBCostingOnTag                               : TB_costing_on,
            pjmvt.GB_IHTOnTag                                     : IHT_costing_on,
            ismvt.IS_CALC_TOTAL_MED_EQUIP_COSTS_V1                : calc_total_med_equip_costs_value,
            pjmvt.PJN_IHTPlanTypeTag                              : plan_type,
        }
        istcu.IS_calc_total_equipment_costs_util(mod_vars_dict, False) # markChange because of calc_maint_costs_as_perc_med_equip_costs_value

    mod_vars_rec = {      
        # Inputs / pre-result / calculated
        #       
        ismvt.IS_VERSION_TAG_V1                               : 1,
        ismvt.IS_DATA_CHANGED_TAG_V1                          : value_bool_false, 
        ismvt.IS_PROJ_VALID_TAG_V1                            : value_bool_false, 
        ismvt.IS_FILE_NAME_TAG_V1                             : value_str,                          
        ismvt.IS_PROJ_VALID_DATE_TAG_V1                       : value_date,    
        ismvt.IS_FACILITY_TYPE_RECORDS_TAG                    : facility_type_records,
        ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG               : facility_med_equip_records,     
        ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG         : facility_MEG_records,    
        ismvt.IS_FACILITY_FURNITURE_RECORDS_TAG_V1            : facility_furniture_records,       
        ismvt.IS_ENTER_CONSTRUCT_COSTS_BY_COMP_TAG_V1         : value_bool_false,  
        ismvt.IS_ENTER_OP_COST_PERC_CONSTRUCT_COST_TAG_V1     : value_bool_false,        
        ismvt.IS_FACIL_TARGET_SETTING_METHOD_TAG_V1           : facility_target_setting_method,  
        ismvt.IS_VEHICLE_TYPE_RECORDS_TAG_V1                  : [],
        ismvt.IS_DIRECT_ENTRY_FUEL_EXPEND_TAG_V1              : value_bool_false,
        ismvt.IS_COST_FUEL_PER_LITER_TAG_V1                   : 1.1,
        ismvt.IS_ICT_EQUIPMENT_RECORDS_TAG_V1                 : [],
        ismvt.IS_PROG_MGMT_DATA_TAG_V1                        : ismvdl.IS_create_prog_mgmt_data_dict(num_years_inputs),
        ismvt.IS_CALC_TOTAL_MED_EQUIP_COSTS_V1                : calc_total_med_equip_costs_value,
        ismvt.IS_CALC_MAINT_COSTS_AS_PERC_MED_EQUIP_COSTS_TAG : calc_maint_costs_as_perc_med_equip_costs_value, # Enter directly/absolute number is default

        # Outputs / results

        ismvt.IS_RES_TOTAL_NUM_FAC_AVAIL_TAG                     : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_TOTAL_COST_BUILD_EQUIP_NEW_FAC_TAG          : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_NEW_FAC_CONSTRUCT_TAG                       : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_TOTAL_NUM_BEDS_AVAIL_TAG                    : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_NEW_FAC_FURNITURE_COSTS_TAG                 : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_FAC_LAND_COSTS_TAG                          : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_NEW_FAC_CONSTRUCT_COSTS_TAG                 : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_NEW_FAC_MED_EQUIP_COSTS_TAG                 : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_FAC_REHAB_COSTS_TAG                         : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_FAC_TOTAL_OP_COSTS_TAG                      : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_OTHER_FAC_OP_COSTS_TAG                      : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_FAC_WATER_COSTS_TAG                         : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_FAC_ELECTRIC_COSTS_TAG                      : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),
        ismvt.IS_RES_VEHIC_AVAIL_TAG                             : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_PURCH_TAG                             : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_PURCH_CAP_COSTS_TAG                   : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_PURCH_CAP_COSTS_BY_FAC_TAG            : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_PURCH_CAP_COSTS_OTHER_NON_FAC_TAG     : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_MAINT_REPAIR_COSTS_TAG                : [], # no default vehicle types
        ismvt.IS_RES_VEHIC_MAINT_REPAIR_COSTS_BY_FAC_TAG         : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_MAINT_REPAIR_COSTS_OTHER_NON_FAC_TAG  : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_FUEL_COSTS_TAG                        : [], # no default vehicle types
        ismvt.IS_RES_VEHIC_FUEL_COSTS_BY_FAC_TAG                 : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_FUEL_COSTS_OTHER_NON_FAC_TAG          : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_DRIVER_SALARIES_TAG                   : [], # no default vehicle types
        ismvt.IS_RES_VEHIC_DRIVER_SALARIES_BY_FAC_TAG            : [], # no default vehicle types 
        ismvt.IS_RES_VEHIC_DRIVER_SALARIES_OTHER_NON_FAC_TAG     : [], # no default vehicle types 
        ismvt.IS_RES_ICT_AVAIL_TAG                               : [], # no default ICT types                                    
        ismvt.IS_RES_ICT_PURCH_TAG                               : [], # no default ICT types  
        ismvt.IS_RES_ICT_CAP_COSTS_TAG                           : [], # no default ICT types
        ismvt.IS_RES_ICT_CAP_COSTS_BY_FAC_TAG                    : [], # no default ICT types
        ismvt.IS_RES_ICT_CAP_COSTS_OTHER_NON_FAC_TAG             : [], # no default ICT types
        ismvt.IS_RES_ICT_MAINT_REPAIR_OP_COSTS_TAG               : [], # no default ICT types
        ismvt.IS_RES_ICT_MAINT_REPAIR_OP_COSTS_BY_FAC_TAG        : [], # no default ICT types
        ismvt.IS_RES_ICT_MAINT_REPAIR_OP_COSTS_OTHER_NON_FAC_TAG : [], # no default ICT types
        ismvt.IS_RES_MED_EQUIP_MAINT_CALIB_COSTS_TB_TAG          : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),

        # TB costing mode
        ismvt.IS_RES_EQUIPMENT_COSTS_DSC_V1                      : ismvd.IS_init_facility_year_arr(num_facility_types, num_years_outputs, 0.0).tolist(),

        # Meta
        ismvt.IS_DEFAULT_MED_EQUIP_GROUP_LIST_META_TAG           : isrd.IS_init_default_MEG_list_meta(facility_med_equip_group_DB, costing_mode, plan_type),
    }

    #Debugging
    #with open('C:\Proj\IHTSampleFile.JSON', 'w') as f:
    #   json.dump(mod_vars_dict, f)

    return mod_vars_rec

    