from datetime import date

import numpy as np

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

import SpectrumCommon.Const.HW.HWConst as hwc
import SpectrumCommon.Const.HW.HWConstLink as hwcl
import SpectrumCommon.Const.HW.HWTags as hwmvt
import SpectrumCommon.Modvars.HW.HWModVarDefs as hwmvd
import SpectrumCommon.Modvars.HW.HWModVarDefsLink as hwmvdl
import SpectrumCommon.Modvars.HW.HWModVarUtil as hwmvu
import SpectrumCommon.Modvars.HW.HWReadDatabases as hwrd

def init_modvars(countryID, first_year, final_year, extra):
    '''
        Initializes Health Workforce 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.
    '''

    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

    costing_mode_mod_vars = {
        pjmvt.GB_IHTOnTag       : IHT_costing_on,
        pjmvt.GB_TBCostingOnTag : TB_costing_on,
        pjmvt.GB_LCOnTag        : LiST_costing_on,
    }

    costing_mode = gbu.get_costing_mode(costing_mode_mod_vars)

    # Load databases
    
    if costing_mode == gbc.GB_LIST_COSTING_MODE:
        staff_salaries_DB = hwrd.HW_load_staff_salaries_DB(countryID)

    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

    staff_type_records = hwmvd.HW_init_staff_type_records(extra[hwcl.HW_IS_FACILITY_RECORDS_TAG_V1], num_years_inputs, costing_mode)
    hwmvd.HW_init_staff_type_target_setting_methods(staff_type_records)
    inserv_train_type_records = hwmvd.HW_init_inserv_train_type_records(num_years_inputs)

    num_staff_types = hwmvu.get_HW_num_staff_types(staff_type_records)

    attrition_type_records = []
    retention_incentive_records = []

    # Meta data
    static_staff_list_meta = hwmvd.HW_init_static_staff_list_meta()

    if costing_mode == gbc.GB_LIST_COSTING_MODE:
        hwrd.HW_set_staff_salaries(staff_type_records, staff_salaries_DB)

    ###################################################################################################################
    # 
    #                                             For testing calculations
    #
    ###################################################################################################################

    # HR_RES_TOTAL_STAFF_TAG_V1, HR_RES_TOTAL_COMPENSATION_TAG_V1
    
    # Target setting method is generally set to Facility staffing standards to start. Set to pop norms, existing plans, and no staff for a 
    # couple of staff for testing.
    # primary_care_doc_rec = hrmvu.get_HR_staff_type_rec_from_curr_ID(staff_type_records, hrc.HR_GEN_PRIM_CARE_DOC_CURR_ID)
    # nurses_rec = hrmvu.get_HR_staff_type_rec_from_curr_ID(staff_type_records, hrc.HR_NURSES_CURR_ID)
    # lab_tech_rec = hrmvu.get_HR_staff_type_rec_from_curr_ID(staff_type_records, hrc.HR_LAB_TECHS_ASSIST_CURR_ID)

    # for sl in acu.GBRange(1, hrc.HR_NUM_STAFFING_LEVELS):
    #     for staff_type_rec in staff_type_records:
    #         hrmvu.set_HR_staff_type_num_in_base_year(staff_type_rec, sl, 100.0 * sl)

    #         # HR_RES_TOTAL_COMPENSATION_TAG_V1. We should already have salaries because there are defaults. These will give us results for benefits.
    #         hrmvu.set_HR_staff_type_annual_real_salary_incr(staff_type_rec, 5)
    #         hrmvu.set_HR_staff_type_benefits(staff_type_rec, 3)
    #         hrmvu.set_HR_staff_type_annual_benefits_adj(staff_type_rec, 2)

    #     hrmvu.set_HR_staff_type_target_setting_method(primary_care_doc_rec, sl, hrc.HR_POP_NORMS_MST_ID)
    #     hrmvu.set_HR_staff_type_target_setting_method(nurses_rec, sl, hrc.HR_EXISTING_PLANS_MST_ID)
    #     hrmvu.set_HR_staff_type_target_setting_method(lab_tech_rec, sl, hrc.HR_NO_STAFF_MST_ID)

    # # HR_RES_STAFF_NEEDING_TO_BE_HIRED_TAG_V1
    # attr_type_rec = hrmvd.HR_create_attrition_type_rec('attrType1', 'burn out')
    # attrition_type_records.append(attr_type_rec)

    # retent_incent_rec = hrmvd.HR_create_retent_incent_rec('retentIncent1', 'work from home option', 1)
    # retention_incentive_records.append(retent_incent_rec)

    # # Transaction-type work
    # for st in acu.GBRange(1, num_staff_types):
    #     staff_type_records[st - 1][hrmvf.HR_STAFF_CURR_ATTRIT_PER_YEAR].append(0)
    #     staff_type_records[st - 1][hrmvf.HR_STAFF_PERC_REC_ATTRIT_REDUC_INCENTS].append(0)
    #     staff_type_records[st - 1][hrmvf.HR_STAFF_ANNUAL_COST_ATTRIT_REDUC_INCENTS].append(0)
    #     staff_type_records[st - 1][hrmvf.HR_STAFF_TARGET_RETENT_INCENT_LEVELS].append(np.full((num_years_full), 0).tolist())
    
    # for staff_type_rec in staff_type_records:
    #     hrmvu.set_HR_staff_type_curr_attr_per_year(staff_type_rec, 1, 20)
    #     hrmvu.set_HR_staff_type_perc_receiv_attrit_reduc_incents(staff_type_rec, 1, 70)
    #     hrmvu.set_HR_retent_incent_reduc_attrit(retent_incent_rec, 1, 15)

    mod_vars_rec = {            
        # Inputs / pre-result / calculated
        hwmvt.HW_VERSION_TAG_V1                                : 1,
        hwmvt.HW_DATA_CHANGED_TAG_V1                           : value_bool_false, 
        hwmvt.HW_PROJ_VALID_TAG_V1                             : value_bool_false, 
        hwmvt.HW_FILE_NAME_TAG_V1                              : value_str,                          
        hwmvt.HW_PROJ_VALID_DATE_TAG_V1                        : value_date,    
        hwmvt.HW_COST_INSERV_TRAIN_BY_PERC_SALARY_TAG_V1       : value_bool_true,
        hwmvt.HW_SHOW_PRESERV_TRAIN_BY_INSTITUTION_TAG_V1      : value_bool_false,  
        hwmvt.HW_STAFF_TYPE_RECORDS_TAG_V1                     : staff_type_records,        
        hwmvt.HW_INSERV_TRAIN_TYPE_RECORDS_TAG_V1              : inserv_train_type_records,  
        hwmvt.HW_ATTRITION_TYPE_RECORDS_TAG_V1                 : attrition_type_records,
        hwmvt.HW_RETENTION_INCENTIVE_RECORDS_TAG_V1            : retention_incentive_records,
        hwmvt.HW_TARG_SCALE_UP_VISITED_TAG_V1                  : np.full((hwc.HW_NUM_STAFFING_LEVELS), False).tolist(),
        hwmvt.HW_TARG_ENROLLMENT_VISITED_TAG_V1                : value_bool_false,                
        hwmvt.HW_TARG_GRADUATION_VISITED_TAG_V1                : value_bool_false,
        hwmvt.HW_TARG_RETENT_INCENT_LEVELS_VISITED_TAG_V1      : value_bool_false,
        # hrmvt.HR_PRESERV_ENROLLMENT_TAG_V1                     : 0,
        # hrmvt.HR_PROJECTED_GRADUATION_TAG_V1                   : 0,                  
        # hrmvt.HR_TOTAL_INSERV_TRAIN_COSTS_BY_TRAIN_TYPE_TAG_V1 : 0,
        # hrmvt.HR_CURR_GRAD_PERC_CURR_ENROLL_TAG_V1             : 0,
        # hrmvt.HR_ATTRITION_RATE_TAG_V1                         : 0,
        # hrmvt.HR_COST_PRESERV_TRAIN_TAG_V1                     : 0, 
        # hrmvt.HR_TOTAL_INSERV_TRAIN_COSTS_BY_STAFF_TAG_V1      : 0,  
        # hrmvt.HR_STAFF_NEEDING_TO_BE_HIRED_TAG_V1              : 0,
        # hrmvt.HR_TOTAL_STAFF_TAG_V1                            : 0,          
        # hrmvt.HR_TOTAL_COMPENSATION_TAG_V1                     : 0,
        hwmvt.HW_PROG_MGMT_DATA_TAG_V1                          : hwmvdl.HW_create_prog_mgmt_data_dict(num_years_inputs),

        # Outputs / results 
        hwmvt.HW_RES_TOTAL_STAFF_TAG_V1                         : hwmvd.HW_init_staff_level_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_TOTAL_COMPENSATION_TAG_V1                  : hwmvd.HW_init_staff_level_staff_type_compens_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_STAFF_NEEDING_TO_BE_HIRED_TAG_V1           : hwmvd.HW_init_staff_level_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_ATTRITION_RATE_TAG_V1                      : hwmvd.HW_init_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_INSERV_TRAIN_COSTS_BY_STAFF_TAG_V1         : hwmvd.HW_init_staff_level_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_INSERV_TRAIN_COSTS_BY_TRAIN_TYPE_TAG_V1    : hwmvd.HW_init_inserv_train_type_year_arr(num_years_outputs, 0.0),
        hwmvt.HW_RES_PRESERV_TRAIN_COSTS_TAG_V1                 : hwmvd.HW_init_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),
        hwmvt.HW_RES_STAFF_PER_10K_POP_TAG_V1                   : hwmvd.HW_init_staff_level_staff_type_year_arr(num_staff_types, num_years_outputs, 0.0),

        hwmvt.HW_STATIC_STAFF_LIST_META_TAG_V1                    : static_staff_list_meta,
    }

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

    return mod_vars_rec

    