import services
import sims4
from event_testing.tests import TunableTestSet
from scheduler import WeeklySchedule
from sims4.localization import TunableLocalizedStringFactory
from sims4.resources import CompoundTypes
from sims4.tuning.tunable import TunableInterval, TunableReference, HasTunableFactory, AutoFactoryInit, TunableList, Tunable, TunedInterval, TunableResourceKey
from sims4.tuning.tunable_base import ExportModes, GroupNames
from tunable_multiplier import TestedSum

class LuckLevel(HasTunableFactory, AutoFactoryInit):
    FACTORY_TUNABLES = {'interval': TunableInterval(description='\n            The interval that this level should be active for.\n            Both ends of this interval are treated as inclusive.\n            Uses the value from the luck stat.\n            ', tunable_type=float, default_lower=-100, default_upper=100, export_modes=ExportModes.ServerXML), 'perceived_value_bias': Tunable(description="\n            When calculating the impact of luck, we will multiply\n            the typical weight of each option with the perceived value\n            to the player, and finally by this multiplier. We can use\n            this multiplier to bias the options towards certain perceived\n            values.\n            \n            For example, if we want this luck level to select options\n            that are perceived as negative, we can tune this multiplier\n            to -1 to 'flip' the weights.\n            \n            For another example, if we want this luck level to bias\n            towards amazing outcomes rather than just okay outcomes,\n            we can tune this multiplier to 5, to emphasize the magnitude\n            of the various options.\n            ", tunable_type=float, default=1, export_modes=ExportModes.ServerXML), 'impact_loot': TunableReference(description='\n            When this loot has an impact on a decision,\n            apply this loot.\n            ', manager=services.get_instance_manager(sims4.resources.Types.ACTION), pack_safe=True, export_modes=ExportModes.ServerXML), 'should_show_impacts': Tunable(description="\n            Should we show any impacts of luck if this is the sim's luck level?\n            ", tunable_type=bool, default=True, export_modes=ExportModes.ServerXML), 'should_use_luck': Tunable(description="\n            Should we use Luck at all if this is the sim's luck level?\n            ", tunable_type=bool, default=True, export_modes=ExportModes.ServerXML), 'loot_on_enter': TunableList(description='\n            Loot that will be applied when sim enters this luck level.\n            ', tunable=TunableReference(manager=services.get_instance_manager(sims4.resources.Types.ACTION), class_restrictions=('LootActions', 'RandomWeightedLoot'), pack_safe=True), export_modes=ExportModes.ServerXML), 'icon': TunableResourceKey(description='\n            The icon image representing this level.\n            ', default=None, tuning_group=GroupNames.UI, resource_types=CompoundTypes.IMAGE, export_modes=ExportModes.All), 'background': TunableResourceKey(description='\n            The background we should use in the UI for this level.\n            ', default=None, tuning_group=GroupNames.UI, resource_types=CompoundTypes.IMAGE, export_modes=ExportModes.All), 'description_text': TunableLocalizedStringFactory(description='\n            The description of this level to show in UI.\n            ', tuning_group=GroupNames.UI, export_modes=ExportModes.All), 'tooltip': TunableLocalizedStringFactory(description='\n            The tooltip associated with this level.\n            ', tuning_group=GroupNames.UI, export_modes=ExportModes.All), 'name': TunableLocalizedStringFactory(description='\n            The name of this level.\n            ', tuning_group=GroupNames.UI, export_modes=ExportModes.ServerXML)}


class LuckTuning:
    PERCEPTION_RANGE = TunedInterval(-100, 100)
    NORMALIZED_LUCK_WEIGHT_RANGE = TunableInterval(description='\n        When we apply luck to weights, we want to do a\n        variety of math operations to the passed in weight\n        to scale it to luck, which can make those weights\n        go wildly out of scale.\n        This tuning brings those values back into a human\n        readable range.\n        \n        Note that any weights <=0 are skipped, so keep both\n        ends of this range above 0.\n        ', tunable_type=float, default_lower=0.01, default_upper=1)
    LUCK_LEVELS = TunableList(description="\n        The levels of luck that an actor can have.\n        If an actor's luck falls within multiple levels'\n        intervals, the first interval in the list will be\n        chosen.\n        ", tunable=LuckLevel.TunableFactory(), export_modes=ExportModes.All)
    SIM_INFO_TRAY_ICON = TunableResourceKey(description='\n        The icon to show in the SimInfoTray when Luck Changes.\n        ', default=None, tuning_group=GroupNames.UI, resource_types=CompoundTypes.IMAGE, export_modes=ExportModes.ClientBinary)
    SIM_INFO_TRAY_HOVER_ICON = TunableResourceKey(description='\n        The icon to show in the SimInfoTray when Luck Changes\n        and the player hovers over the button.\n        ', default=None, tuning_group=GroupNames.UI, resource_types=CompoundTypes.IMAGE, export_modes=ExportModes.ClientBinary)
    LUCK_STAT = TunableReference(description='\n        The statistic that tracks the current luck for a given actor.\n        ', manager=services.get_instance_manager(sims4.resources.Types.STATISTIC), pack_safe=True)
    SHOULD_HAVE_LUCK_TESTS = TunableTestSet(description='\n        Tests to verify if the given Actor should have Luck.\n        Note: this should not include whether Luck is enabled or\n        not. That is handled separately.\n        ')
    LUCK_MODIFIERS = TestedSum.TunableFactory(description='\n        If we, for some reason, want to add modifiers to the luck stat,\n        without actually modifying the luck stat itself, we can do so here.\n        For example, if we want lucky charms that increase luck when nearby,\n        we can put those proximity checks in here.\n        ')
    LUCK_REFRESH_SCHEDULE = WeeklySchedule.TunableFactory(description="\n        The schedule on which to refresh an individual sim's luck.\n        ")

