#####################################################################
#                MISSIONS
#####################################################################

init python:

    class MissionSystem():
        def __init__(self):
            self.missions = [] # open missions

        def acceptMission(self, mission):
            self.missions.append(mission) 
            sLoc = GAME.getSpaceLoc(mission.sLocID)
            if not sLoc.found: # mark new loc on map
                sLoc.found = True
            return

        # ===== CR-0533 START
        def getLocActive(self, sLocID, mode = "cond_met"):
            found = []
            for i in self.missions:
                if i.kind in  ["transport", "smuggling"]:
                    if sLocID == i.sLocID:
                        if eval(i.cond) and mode == "cond_met":
                            found.append(i) 
                        elif mode == "loc_only":
                            return(i)
                elif i.kind == "bounty":
                    if sLocID == i.sLocID:
                        found.append(i)
            if found == []:
                return(False)
            # identify nex up mission
            next_up = sorted(found, key=lambda x: x.due)[0]
            return(next_up)
        # ===== CR-0533 END

        def getDueMissions(self, mDay=False):
            if mDay:
                missions = [x for x in self.missions if x.due == mDay]
            else:
                missions = list(self.missions)
            return(missions)
        
        def getExpiredMissions(self):
            missions = []
            for m in self.missions:
                if m.due < GAME.day:
                    missions.append(m)
            return(missions)

        def getReserved(self): # reserved contingents of wares 
            reserved = {}
            for mission in self.getDueMissions():
                if mission.kind in ["transport", "smuggling"]:
                    if "wareID" in mission.attr.keys():
                        wareID = mission.attr["wareID"]
                        amount = mission.attr["amount"]
                        if wareID not in reserved.keys():
                            reserved[wareID] = 0
                        reserved[wareID] += amount 
            return(reserved)

        def getReserved2(self):
            reserved2 = {}
            for mission in self.getDueMissions():
                if mission.kind in ["transport", "smuggling"]:
                    if "wareID" in mission.attr.keys():
                        wareID = mission.attr["wareID"]
                        amount = mission.attr["amount"]
                        if wareID not in reserved2.keys():
                            reserved2[wareID] = 0
                        if reserved2[wareID] == 0 or reserved2[wareID] > amount:
                            reserved2[wareID] = amount
            return(reserved2)

        def purgeMission(self, mission):
            self.missions.remove(mission)
            return()

        def rollMission(self, kind, lvl, tags=[], attr={}):

            if "starSys" in attr.keys():
                starSys = attr["starSys"]
            else:
                starSys = GAME.getStarSys()

            zFactors = {0: 1.3, 25: 1.4, 50: 1.5, 75: 1.7, 100: 2.0} # CR-0392

            mID = "MID{}-{}".format(kind.title(), GAME.getUniqueID())
            mKind = kind

            if kind == "transport":    
                mName = "Transport Mission" 

                # choose wares 
                if "wares" in attr.keys(): # predefined wares
                    wares = list(attr["wares"])
                    amount = len(wares)
                    wareID = wares[0]

                else: # random wares
                    amount = random.randint(4,10+5*lvl) # CR-0392
                    allWares = [x.ID for x in GAME.items.values() if x.kind == "ware" and "no_mission" not in x.tags and starSys.isLegal(x.ID)]
                    waresChoices = []
                    for i in allWares:
                        wareOK = True
                        ware = GAME.items[i]
                        # remove items based on mission level and other conditions
                        if lvl in [1,2]:
                            if "exclusive" in ware.attr.keys():
                                if ware.attr["exclusive"] not in ["SSIDIltari"]:
                                    wareOK = False
                            if ware.ID in ["ITMEternium"]:
                                wareOK = False
                        if wareOK:
                            waresChoices.append(ware.ID)
                    wareID = random.choice(waresChoices)
                    if wareID == "ITMEternium":
                        amount  = random.randint(1,5)
                    wares = [wareID]* amount


                # chose due date 
                mDue = GAME.day + random.randint(1,5) 
                if "due" in attr.keys():
                    mDue = attr["due"]

                # chose target location
                #GAME.log.append(missionSys)
                if starSys.ID == "SSIDArellarti":
                    if "sLocID" in attr.keys():
                        mSLocID = attr["sLocID"]
                    else:
                        mSLocID = random.choice(["LIDStationArellarti", "LIDRendezvousArellarti25", "LIDRendezvousArellarti50", "LIDRendezvousArellarti75", "LIDRendezvousArellarti100", "LIDDomeArellarti", "LIDLabsArellarti", "LIDAsteroidsArellarti"])
                else:
                    if "sLocID" in attr.keys():
                        mSLocID = attr["sLocID"]                    
                    elif not GAME.getStarSys().isLegal(wareID):
                        mSLocID = random.choice(["LIDTenaris", "LIDRendezvous100", "LIDRendezvous75", "LIDRendezvous50", "LIDRendezvous25", "LIDPirate"])                    
                    else:
                        mSLocID = random.choice(["LIDIltari", "LIDStationIltari", "LIDRendezvous100", "LIDRendezvous50", "LIDRendezvous75", "LIDRendezvous25", "LIDAsteroidsIltari"])

                # chose reward
                sLoc = GAME.getSpaceLoc(mSLocID)

                
                mReward = int (amount * max(GAME.items[wareID].price*1.2, 220) * zFactors[sLoc.zone] ) # CR-0392
                
                if not GAME.getStarSys().isLegal(wareID):
                    mReward = mReward * 2
                mCond = "GAME.ship.cargo.count(GAME.items['{}']) >= {}".format(wareID, amount)
                mReq = {} 
                mAttr = {"wareID": wareID, "amount": amount}
                mission = Mission(mID, mName, mKind, mSLocID, mDue, mCond, mReq, mReward, mAttr)
                # Unlock special location? 

            elif kind == "smuggling":    
                mName = "Smuggling Mission" 
                # choose wares 
                if "wares" in attr.keys():
                    wares = list(attr["wares"])
                    amount = len(wares)
                    wareID = wares[0]
                else:
                    amount = random.randint(4,5*lvl) # CR-0392
                    wareID = random.choice([x.ID for x in GAME.items.values() if x.ID in ['ITMSlaves', "ITMDrugs"]])
                    wares = [wareID]* amount
                # chose due date 
                mDue = GAME.day + random.randint(1,5) 
                if "due" in attr.keys():
                    mDue = attr["due"]

                # chose target location

                if "sLocID" in attr.keys():
                    mSLocID = attr["sLocID"]
                else:
                    mSLocID = random.choice(["LIDTenaris", "LIDRendezvous100", "LIDRendezvous75", "LIDRendezvous50", "LIDRendezvous25", "LIDPirate"])                    

                # chose reward
                sLoc = GAME.getSpaceLoc(mSLocID)

                # mReward = amount * int(GAME.items[wareID].price*2) * int((sLoc.zone)/25.0+1.0)

                mReward = int (amount * max(GAME.items[wareID].price*2.0, 1100) * zFactors[sLoc.zone] ) # CR-0392


                mCond = "GAME.ship.cargo.count(GAME.items['{}']) >= {}".format(wareID, amount)
                mReq = {} 
                mAttr = {"wareID": wareID, "amount": amount}
                mission = Mission(mID, mName, mKind, mSLocID, mDue, mCond, mReq, mReward, mAttr)
                # Unlock special location? 

            elif kind == "bounty":
                if kind == "bounty":    
                    mName = "Bounty Mission" 
                    # choose hostiles and level 
                    mLvl = lvl 
                    mProfile = random.choice(
                        {
                            1: ["hostile_1", "hostile_1a"],
                            2: ["hostile_2", "hostile_2a", "hostile_2b"],
                            3: ["hostile_3", "hostile_3a", "hostile_3b", "hostile_3c", "hostile_3d"  ],
                            4: ["hostile_4" ],
                            5: ["hostile_5b"]
                        }[mLvl]) 
                    
                    # chose due date 
                    mDue = GAME.day + random.randint(1,5) 
                    # chose target location
                    if "sLoc" in attr.keys():
                        mSLocID = attr["sLoc"]
                    else:
                        mSLocID = random.choice(["LIDTenaris", "LIDRendezvous100", "LIDRendezvous75", "LIDRendezvous75", "LIDRendezvous25", "LIDAsteroidsIltari"])
                    # chose reward
                    sLoc = GAME.getSpaceLoc(mSLocID)
                    mReward = int (2 * mLvl  * random.randint(20000,25000) * zFactors[sLoc.zone] ) 
                        
                    mCond = "False"
                    mReq = {} 
                    mAttr = {"mProfile": mProfile}
                    mission = Mission(mID, mName, mKind, mSLocID, mDue, mCond, mReq, mReward, mAttr)
                    # Unlock special location? 
                    mission.lvl = lvl

            return(mission)


    class Mission():
        def __init__(self, ID, name, kind, sLocID, due, cond, req, reward, attr):
            self.ID = ID
            self.name = name
            self.kind = kind # bounty, smuggling, transport
            self.due = due # due date to accomplish mission
            self.sLocID = sLocID # target location to trigger checks on arrival
            self.cond = cond # additional conditions for accomplishment
            self.req = req # req to receive
            self.attr = attr
            self.reward = reward
            self.lvl = 1


#####################################################################
#					MISSIONDB		
#####################################################################


#####################################################################
#					MISSION CREATION		
#####################################################################
label missions_restock(actor, spaceLoc, mList, attr= {}, tags= []): # CR-0392


    # 
    # star system mission managers
    if actor == mission_mgr_iltari:
        $ spaceLoc = GAME.getSpaceLoc("LIDPirate") # any location that allows all mission types
        $ mList = ["transport"]
        if 'pirate_affiliate' in GAME.mc.done:
            $ mList += ["smuggling", "bounty"]    
        $ starSys = GAME.starSys["SSIDIltari"]

    elif actor == mission_mgr_arellarti:
        $ spaceLoc = GAME.getSpaceLoc("LIDStationArellarti") # any location that allows all mission types
        $ mList = ["transport"]
        $ starSys = GAME.starSys["SSIDArellarti"]
    else:
        $ starSys = GAME.getStarSys()


    # mission refresh
    if "refresh" not in tags:
        if actor.hasDoneToday("missions"):
            return()
    python:
        if "mLimit" in attr.keys():
            mLimit = attr["mLimit"]
        else:
            mLimit = (random.randint(2,6))

        actor.missions = []
        lvl = GAME.mc.lvl
        limits = {"transport": 7, "smuggling": 3, "bounty": 3}
        for mType in mList:
            for i in range(limits[mType]):
                if mType == "bounty":
                    mission = GAME.missionSys.rollMission(mType, random.choice([1,1,1,1,1,2,2,2,2,2,2,3,3,3,4,4,5]), [], {"starSys": starSys}) # CR-0392
                    actor.missions.append(mission)

                elif mType == "transport":
                    mission = GAME.missionSys.rollMission(mType, lvl, [], {"starSys": starSys}) # CR-0392
                    item = GAME.items[mission.attr["wareID"]]
                    if mission.sLocID != spaceLoc.ID and spaceLoc.isLegal(item.ID):
                        actor.missions.append(mission)

                elif mType == "smuggling":
                    mission = GAME.missionSys.rollMission(mType, lvl, [], {"starSys": starSys}) # CR-0392
                    item = GAME.items[mission.attr["wareID"]]
                    if mission.sLocID != spaceLoc.ID and spaceLoc.isLegal(item.ID):
                        actor.missions.append(mission)

    return()

#####################################################################
#					MANAGEMENT		
#####################################################################    
screen mission_selector_scr(missions, mTitle = False, mFilter):
    image "05_gui/mask 50.png"
    if mTitle:
        $ msg = mTitle
    else: 
        $ msg = "AVAILABLE MISSIONS"
    text msg size FSIZE_LARGE pos 20,90 xalign 0.0 outlines [ (absolute(5), "#0099cc", absolute(0), absolute(0)) ]

    # filters 
    hbox ypos 100 xalign 0.5 spacing 5:
        for i in ["transport", "smuggling", "bounty"]:
            if mFilter[i]:
                $ bCol = "#0099ccff"
            else:
                $ bCol = "#888888ff"
            frame xsize 140 ysize 30 background Solid (bCol):
                text i.title() xalign 0.5 yalign 0.5 size FSIZE_MED # CR-0298
                button action Return(["filter", i])    

    # missions
    side "c r":
        area 65,165,1800,785
        # center
        viewport id "vp":
            draggable True 
            mousewheel True

            vbox xsize 1660 ypos 240 spacing 8:
                for i in missions:
                    $koff= 0
                    $ C_B, C_E = C_HI_B, C_HI_E
                    if i.kind == "smuggling":
                        $koff = 15
                        $ C_B, C_E = C_YE_B, C_YE_E
                    elif i.kind == "bounty":
                        $ C_B, C_E = C_OR_B, C_OR_E
                        $koff = 30

                    # ===== CR-0442 START =====
                    if mFilter[i.kind]:
                        frame xsize 1800 ysize 50 yoffset koff background Solid("#ffffff33"):
                            $ dueDays = i.due-GAME.day
                            if dueDays == 0:
                                $ dueDays = C_YE_B+"Today!"+ C_YE_E
                            text "{}".format(C_B+i.name+ C_E) xpos 20 yalign 0.5 size FSIZE
                            if i.sLocID:
                                $ C_B_Z, C_E_Z = "", ""
                                if GAME.ship.canReach(i.sLocID):
                                    $ C_B_Z, C_E_Z = C_GR_B, C_GR_E
                                $ sLoc = GAME.getSpaceLoc(i.sLocID)
                                text "{}{}{}".format(C_B_Z,sLoc.name, C_E_Z) xpos 300 yalign 0.5 size FSIZE
                            if i.kind in ["transport", "smuggling"]:
                                $ itemID = i.attr["wareID"]
                                $ amount = i.attr["amount"]
                                text "{} ({}x)".format(GAME.items[itemID].getName(["cap", "col"]), amount) xpos 560 yalign 0.5 size FSIZE
                            elif i.kind == "bounty":
                                text C_B+"Difficulty Level {}".format(i.lvl)+C_E xpos 560 yalign 0.5 size FSIZE

                            text "Days Left: {}".format(dueDays) xpos 1100 yalign 0.5 size FSIZE # CR-0525
                            text C_GO_B+"{:,} Cr".format(i.reward)+C_GO_E xpos 1040 xalign 1.0 yalign 0.5 size FSIZE
                            frame xsize 160 ysize 30 background Solid ("#0099ccff") yalign 0.5 xpos 1450:
                                text "Fee {:,} Cr".format(int(i.reward*0.05)) xalign 0.5 yalign 0.5 size FSIZE_MED
                                button action Return(["sign",i])
                            if i.kind in ["transport", "smuggling"]:
                                $ itemID = i.attr["wareID"]
                                #samplecode: sLoc.wares.count(GAME.items["ITMOreUranium"])
                                #$ sDock = GAME.getSpaceLoc().wares
                                if spaceLoc.isLegal(GAME.items[itemID]):
                                    $ localamount = GAME.getSpaceLoc().wares.count(GAME.items[itemID])
                                    $ warehouseamount = GAME.base.wares.count(GAME.items[itemID])
                                    if localamount > 0 and GAME.ship.canReach(i.sLocID):
                                        if warehouseamount < 1:
                                            text "[localamount] for Sale" xpos 1300 yalign 0.5 size FSIZE_MED
                                        else:
                                            text "[localamount] for Sale\n[warehouseamount] in Storage" xpos 1300 yalign 0.5 size FSIZE_MED yoffset 1
                                    elif warehouseamount > 0 and GAME.ship.canReach(i.sLocID):
                                        text "[warehouseamount] in Storage" xpos 1300 yalign 0.5 size FSIZE_MED

                                if GAME.ship.cargoAssignable(i.attr["wareID"], i.attr["amount"]):
                                    text "[C_GR_B]{} In Cargo[C_GR_E]".format(GAME.ship.cargo.count(GAME.items[itemID])) xpos 1650 yalign 0.5 size FSIZE_MED
                                else:
                                    text "{} Short".format(GAME.ship.cargoAssignable(i.attr["wareID"], i.attr["amount"], "delta")) xpos 1650 yalign 0.5 size FSIZE_MED
                    # ===== CR-0442 END ====
        # right
        vbar value YScrollValue("vp") xoffset 20

    #####################################################################
    #                EXIT BUTTON, KEYS, ...
    #####################################################################
    frame xsize 350 ysize 64 pos 0,980 background Solid("#00000000") padding 0,0:
        image "05_gui/gui_menu_option.png" yalign 0.5
        button action Return(False)
        textbutton "Exit (X)" yalign 0.5 action Return(False) xpos 20 # CR-0587
        key "x" action Return(False)
        key "X" action Return(False)
        key "K_SPACE" action Return(False)

    vbox  xalign 0.5 yalign 0.95:
        text "[C_YE_B]Illegal Wares - Cargo Cloak Recommended[C_YE_E] / [C_OR_B]Combat Mission - Shields and Armaments Required[C_OR_E] / [C_GR_B]In Cargo = Non-Reserved Cargo Available[C_GR_E]" size FSIZE_MED


#####################################################################
#					COMPLETION CHECKS		
#####################################################################
 
label mission_overnight_check():
    $ missions = GAME.missionSys.getExpiredMissions()
    while missions:
        $ mission = missions.pop(0)
        queue sound "audio/notify.wav"
        call large_notify("MISSION FAILED", "You did not successfully complete your {}{} Mission{} in time. As a consequence, your reputation has been negatively affected.".format(C_HI_B, mission.kind.title(), C_HI_E), ["Continue"], "05_gui/ico Ship.png", "red") from _call_large_notify_42 
        call attr_mod(GAME.mc, "REP", -1, 0, 100, True) from _call_attr_mod_77
        $ GAME.missionSys.purgeMission(mission)

    return()

#####################################################################
#					MISSION SCRIPTS		
#####################################################################
label mission_scripts(mission, mode = "on_complete"):

    #####################################################################
    #                MISSION SPECIFIC SCRIPTS
    #####################################################################
    if mission.ID == "Dummy":
        "Do stuff here"

    #####################################################################
    #                CATEGORY SPECIFIC SCRIPTS
    #####################################################################

    # generic post processing

    elif mission.kind == "transport" and mode == "on_complete":
        $ amount = mission.attr["amount"] 
        $ item = GAME.items[mission.attr["wareID"]] 
        python:
            for x in range(amount):
                GAME.ship.unloadWare(item.ID)        
        play sound "audio/success.wav"
        call simple_notify("MISSION COMPLETE", "{} ({}x)".format(mission.name, amount), ["Continue"], "08_items/ico {}.png".format(item.ID, amount)) from _call_simple_notify_63        
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_22
        call transaction("Transport Rewards", mission.reward, True) from _call_transaction_33
        call attr_mod(GAME.mc,"REP", 1,30,100, True) from _call_attr_mod_78


    elif mission.kind == "smuggling" and mode == "on_complete":
        $ amount = mission.attr["amount"] 
        $ item = GAME.items[mission.attr["wareID"]] 
        python:
            for x in range(amount):
                GAME.ship.unloadWare(item.ID)        
        play sound "audio/success.wav"
        call simple_notify("MISSION COMPLETE", "{} ({}x)".format(mission.name, amount), ["Continue"], "08_items/ico {}.png".format(item.ID, amount)) from _call_simple_notify_64        
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_23
        call transaction("Smuggling Rewards", mission.reward, True) from _call_transaction_34
        call attr_mod(GAME.mc,"NOT", 1,30,100, True) from _call_attr_mod_79
        $ GAME.mc.hasDone("first_smuggling") # CR-0300
        if khelara in GAME.crew and khelara.attr["APP"] < 3 and "seen_smuggling" not in khelara.done:
            $ khelara.hasDone("seen_smuggling")

    elif mission.kind == "bounty" and mode == "on_complete":
        play sound "audio/success.wav"
        call simple_notify("MISSION COMPLETE", mission.name, ["CONTINUE"], "05_gui/ico_gui_hostile_human.png") from _call_simple_notify_65        
        play sound "audio/success.wav"
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_24
        call transaction("Bounty Rewards", mission.reward, True) from _call_transaction_35
        call attr_mod(GAME.mc,"NOT", 1,50,100, True) from _call_attr_mod_80

        if khelara in GAME.crew and khelara.attr["APP"] < 3 and "seen_bounty" not in khelara.done:
            $ khelara.hasDone("seen_bounty")


    call achievement_updater() from _call_achievement_updater

    return()
