import services
from interactions.utils.tunable_icon import TunableIcon
from sims.sim_info_types import Age
from sims4.localization import TunableLocalizedString
from sims4.log import Logger
from sims4.tuning.instances import HashedTunedInstanceMetaclass
from sims4.tuning.tunable import TunableSet, TunableReference, TunableRange, Tunable, OptionalTunable, TunableEnumSet
from sims4.resources import Types as ResourceTypes
from sims4.tuning.tunable_base import ExportModes, GroupNames
logger = Logger('CasPreferences', default_owner='mjuskelis')

class CasPreferenceGroup(metaclass=HashedTunedInstanceMetaclass, manager=services.get_instance_manager(ResourceTypes.CAS_PREFERENCE_GROUP)):
    INSTANCE_TUNABLES = {'name': TunableLocalizedString(description='\n            The name of this group.\n            ', export_modes=ExportModes.ClientBinary), 'header_name': TunableLocalizedString(description='\n            The name of this group that we want to use in header contexts.\n            ', export_modes=ExportModes.ClientBinary), 'detailed_description': TunableLocalizedString(description="\n            A description used to help explain what this group represents.\n            Used as a tooltip for the group's tab in CAS.\n            ", export_modes=ExportModes.ClientBinary), 'categories': TunableSet(description='\n            The categories that are in this group.\n            ', tunable=TunableReference(description='\n                ', manager=services.get_instance_manager(ResourceTypes.CAS_PREFERENCE_CATEGORY), pack_safe=True, export_modes=ExportModes.All), export_modes=ExportModes.All), 'icon': TunableIcon(description='\n            The icon that represents this group.\n            ', export_modes=ExportModes.ClientBinary), 'icon_selected': TunableIcon(description='\n            The icon to show when this group is selected.\n            ', export_modes=ExportModes.ClientBinary), 'help_tooltip': TunableLocalizedString(description="\n            The tooltip to use on the help icon in CAS when this group\n            is selected.\n            \n            Parameters:\n            1. This group's capacity.\n            2. This group's name.\n            ", export_modes=ExportModes.ClientBinary), 'capacity': TunableRange(description='\n            The number of preferences from this group that can be selected.\n            ', tunable_type=int, minimum=1, default=15, export_modes=ExportModes.All), 'telemetry_name': Tunable(description='\n            The telemetry name for this preference group. Defining this field will\n            cause the number of traits on a given Sim to be counted for GAME:CASS:EXIT\n            telemetry.\n            ', tunable_type=str, default=None, export_modes=ExportModes.ClientBinary), 'timeline_label_name': Tunable(description='\n            The name of the label that we want to use for this preference group.\n            This is used in several places in the UI.\n            ', tunable_type=str, default='preference', tuning_group=GroupNames.UI, export_modes=ExportModes.ClientBinary), 'items_name_positive': TunableLocalizedString(description="\n            The name of the 'positive' items for this group,\n            such as 'Likes'. Should be plural.\n            ", export_modes=ExportModes.All), 'items_name_negative': TunableLocalizedString(description="\n            The name of the 'negative' items for this group,\n            such as 'Dislikes'. Should be plural.\n            ", export_modes=ExportModes.All), 'items_name_positive_header_formatted': TunableLocalizedString(description='\n            A version of Items Name Positive,\n            formatted as a header.\n            ', export_modes=ExportModes.ClientBinary), 'items_name_negative_header_formatted': TunableLocalizedString(description='\n            A version of Items Name Negative,\n            formatted as a header.\n            ', export_modes=ExportModes.ClientBinary), 'show_flair': Tunable(description="\n            If checked, it will turn on a flair (glow) to call player's attention to that group\n            ", tunable_type=bool, default=False, tuning_group=GroupNames.UI, export_modes=ExportModes.ClientBinary), 'none_selected_text': TunableLocalizedString(description='\n            The text we want to use for this preference group when a sim \n            has not selected any items for this group.\n            ', export_modes=ExportModes.ClientBinary), 'ages': TunableEnumSet(description='\n            The allowed ages for this Preference Group.\n            ', enum_type=Age, enum_default=None, export_modes=ExportModes.ClientBinary, allow_none=False), 'randomization_minimum_required_likes': TunableRange(description='\n            When randomizing, what are the minimum number of likes\n            that must be selected?\n            ', tunable_type=int, minimum=1, default=1, export_modes=ExportModes.All), 'randomization_minimum_required_dislikes': TunableRange(description='\n            When randomizing, what are the minimum number of dislikes\n            that must be selected?\n            ', tunable_type=int, minimum=1, default=1, export_modes=ExportModes.All), 'counter_text': TunableLocalizedString(description='\n            The text we want to use for this preference group to show the number\n            of selected likes/dislikes for each category.\n            ', export_modes=ExportModes.ClientBinary), 'like_button_text': TunableLocalizedString(description='\n            The text we want to use for this preference group to select that\n            the sim likes the category.\n            ', export_modes=ExportModes.ClientBinary), 'dislike_button_text': TunableLocalizedString(description='\n            The text we want to use for this preference group to select that\n            the sim dislikes the category.\n            ', export_modes=ExportModes.ClientBinary)}

    @classmethod
    def _verify_tuning_callback(cls):
        max_possible_preferences = 0
        minimum_needed = cls.randomization_minimum_required_likes + cls.randomization_minimum_required_dislikes
        for category in cls.categories:
            max_possible_preferences += category._randomization_number_of_preferences.upper_bound
        if max_possible_preferences < minimum_needed:
            logger.error('Preference Group {} cannot satisfy its minimum requirements!\n\tMinimum Wanted: {},\n\tMax Possible from Categories: {}', cls, minimum_needed, max_possible_preferences)

