from copy import deepcopy


import SpectrumCommon.Const.PJ.PJNTags as pjmvt

import SpectrumCommon.Const.IS.ISTags as ismvt
import SpectrumCommon.Const.IS.ISModVarFields as ismvf
import SpectrumCommon.Modvars.IS.ISReadDatabases as isrd

# Notes:
#
#   1. The only tangible purpose of versions on MVs is to be able to update them appropriately for existing projections so those projections can run with the
#      current codebase. The only code that ever checks MV versions is in the XXUpdateModvars file. If you just added a new field, you could just check and see if
#      the field is in the MV and add it if it's not without changing the version on the MV. Similarly, if you added a new dimension, you could just extend the
#      dimension of a MV without creating a new version. Changing the version number of a MV does gives us more of a history to follow, but doesn't do more
#      for us programmatically. Also, if you change the version of a MV, all clients using that MV need to update their code to use the latest MV.
#      Changing the version of a MV is only really useful if the MV undergoes a major structural change that would make it difficult to
#      manipulate the existing version of that MV otherwise, or if we would like to apply a correction to all previous versions of a MV.
#
#   2. You cannot base logic on whether a current MV tag exists in the code below.  It will always exist, because before this gets called, all missing MVs
#      will get added to the projection.
#
#   3. To trigger this, create a projection, say on the client, save, and grab it's projection ID (in Chrome, F12 --> Application --> session storage).
#      Change GB_PM_Version in GBConst or UpdateModvars will get skipped.  Add proj ID to Postman environment. Call Login, then GetModvars to get the library ID and put that
#      into the Postman environment. Then call OpenProjection. Make sure to leave the projection on the client open  while doing this because the proj ID changes when
#      you open/close. Then call SaveProjection. You should now be able to call Calculate and see the modified MV there where it's used. Don't forget to change
#      the version number back after you finish testing and trash the test projection.
#
def IS_UpdateModvars(projection, created_projection):

    if IS_FACILITY_TYPE_RECORDS_TAG_V1 in projection:
        _convert_facility_type_records_1(projection, IS_FACILITY_TYPE_RECORDS_TAG_V1)

    # This was a part of _convert_facility_type_records_1, but forgot that the IS module was being turned on with LiST projections (IS is needed for HW calcs),
    # so extend this code toall costing modes. Not changing the tag version for facility type records so the client/DPS doesn't need to change it too.
    if ismvt.IS_FACILITY_TYPE_RECORDS_TAG in projection:
        for rec in projection[ismvt.IS_FACILITY_TYPE_RECORDS_TAG]:
            # Before we only had a generic total equipment cost, but then we added maintenance and calibration costs. The sum of the three
            # is really the total equipment cost and total equipment cost is really the purchase cost of the equipment. Change the name so we
            # don't get confused.
            if 'totalEquipmentCost' in rec:
                rec['equipmentPurchaseCost'] = rec.pop('totalEquipmentCost')

    #####

    if IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V1 in projection:
        _convert_med_equip_group_records_1(projection, IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V1)
        _convert_med_equip_group_records_2(projection, ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG)

    elif IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V2 in projection:
        _convert_med_equip_group_records_2(projection, IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V2)

    #####

    if IS_FACILITY_MED_EQUIP_RECORDS_TAG_V1 in projection:
        _convert_med_equip_records_1(projection, IS_FACILITY_MED_EQUIP_RECORDS_TAG_V1)
        _convert_med_equip_records_2(projection, ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG)

    elif IS_FACILITY_MED_EQUIP_RECORDS_TAG_V2 in projection:
        _convert_med_equip_records_2(projection, IS_FACILITY_MED_EQUIP_RECORDS_TAG_V2)

    #####

    # delete tags
    for tag in IS_TagsForDeletion:
        if tag in projection:
            del projection[tag]

    return projection

IS_FACILITY_TYPE_RECORDS_TAG_V1                = '<IS_FacilityRecords_V1>'
IS_FACILITY_MED_EQUIP_RECORDS_TAG_V1           = '<IS_FacilityMedEquipRecords_V1>'
IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V1     = '<IS_FacilityMedEquipGroupRecords_V1>'
IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V2     = '<IS_FacilityMedEquipGroupRecords_V2>'
IS_FACILITY_MED_EQUIP_RECORDS_TAG_V2           = '<IS_FacilityMedEquipRecords_V2>'

IS_TagsForDeletion = [
    IS_FACILITY_TYPE_RECORDS_TAG_V1,
    IS_FACILITY_MED_EQUIP_RECORDS_TAG_V1,
    IS_FACILITY_MED_EQUIP_RECORDS_TAG_V2,
    IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V1,
    IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG_V2
]

def _convert_facility_type_records_1(projection, facility_type_records_tag):
    # New fields were added for TB app.
    facility_type_records = projection[facility_type_records_tag]

    if projection[pjmvt.GB_TBCostingOnTag]:
        for rec in facility_type_records:
            if ismvf.IS_FACIL_MED_EQUIP_MAINT_COST not in rec:
                rec[ismvf.IS_FACIL_MED_EQUIP_MAINT_COST] = 0

            if ismvf.IS_FACIL_MED_EQUIP_CALIB_COST not in rec:
                rec[ismvf.IS_FACIL_MED_EQUIP_CALIB_COST] = 0

            # Before we only had a generic total equipment cost, but then we added maintenance and calibration costs. The sum of the three
            # is really the total equipment cost and total equipment cost is really the purchase cost of the equipment. Change the name so we
            # don't get confused.
            if 'totalEquipmentCost' in rec:
                rec['equipmentPurchaseCost'] = rec.pop('totalEquipmentCost')

    if facility_type_records_tag != ismvt.IS_FACILITY_TYPE_RECORDS_TAG:
        projection[ismvt.IS_FACILITY_TYPE_RECORDS_TAG] = deepcopy(facility_type_records)

def _convert_med_equip_group_records_1(projection, med_equip_group_records_tag):
    # String constants were added for facility medical equipment group records.
    facility_MEG_records = projection[med_equip_group_records_tag]

    for rec in facility_MEG_records:
        if ismvf.IS_FACIL_MEG_STR_CONST not in rec:
            rec[ismvf.IS_FACIL_MEG_STR_CONST] = ''

    if med_equip_group_records_tag != ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG:
        projection[ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG] = deepcopy(facility_MEG_records)

def _convert_med_equip_group_records_2(projection, med_equip_group_records_tag):
    # String constants were added for facility medical equipment group records.
    facility_MEG_records = projection[med_equip_group_records_tag]
    facility_type_records = projection[ismvt.IS_FACILITY_TYPE_RECORDS_TAG]
    TB_costing_on = projection[pjmvt.GB_TBCostingOnTag]

    # Get the default medical equipment group records.
    facility_med_equip_group_DB = isrd.IS_load_facility_med_equip_group_DB()
    facility_MEG_records_DB = isrd.IS_init_facility_MEG_records(facility_med_equip_group_DB, TB_costing_on)

    # Make sure every facility type has at least one MEG record. If one is missing, add it.
    for fac_type_rec in facility_type_records:

        MEG_recs_for_fac_type = [MEG_rec for MEG_rec in facility_MEG_records if MEG_rec['facilityTypeID'] == fac_type_rec['facilityTypeID']]

        # If no MEG records were found for the facility type, add the default ones from the database.
        if len(MEG_recs_for_fac_type) == 0:
            MEG_recs_for_fac_type_DB = [MEG_rec for MEG_rec in facility_MEG_records_DB if MEG_rec['facilityTypeID'] == fac_type_rec['facilityTypeID']]

            for MEG_rec_DB in MEG_recs_for_fac_type_DB:
                facility_MEG_records.append(deepcopy(MEG_rec_DB))

    if med_equip_group_records_tag != ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG:
        projection[ismvt.IS_FACILITY_MED_EQUIP_GROUP_RECORDS_TAG] = deepcopy(facility_MEG_records)

def _convert_med_equip_records_1(projection, med_equip_records_tag):
    # String constants were added for facility equipment records.
    facility_equip_records = projection[med_equip_records_tag]

    for rec in facility_equip_records:
        if ismvf.IS_FACIL_EQUIP_STR_CONST not in rec:
            rec[ismvf.IS_FACIL_EQUIP_STR_CONST] = ''

    if med_equip_records_tag != ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG:
        projection[ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG] = deepcopy(facility_equip_records)

def _convert_med_equip_records_2(projection, med_equip_records_tag):
    # String constants were added for facility equipment records.
    facility_equip_records = projection[med_equip_records_tag]

    if projection[pjmvt.GB_TBCostingOnTag]:
        for rec in facility_equip_records:
            if ismvf.IS_FACIL_EQUIP_MAINT_COST not in rec:
                rec[ismvf.IS_FACIL_EQUIP_MAINT_COST] = 0

            if ismvf.IS_FACIL_EQUIP_CALIB_COST not in rec:
                rec[ismvf.IS_FACIL_EQUIP_CALIB_COST] = 0

    if med_equip_records_tag != ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG:
        projection[ismvt.IS_FACILITY_MED_EQUIP_RECORDS_TAG] = deepcopy(facility_equip_records)
