#####################################################################
#                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

        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)

        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={}):
            starSys = GAME.starSys[attr.get("starSys", GAME.getStarSys().ID)]
            mStarSysID = starSys.ID

            rewSysFactors = {"SSIDIltari": 1.0, "SSIDArellarti": 1.5, "SSIDXenos": 2.0, "SSIDQuthor": 1.5 }
            rewZoneFactors = {0: 1.3, 25: 1.5, 50: 1.7, 75: 1.8, 100: 2.0}

            mKind = kind

            #####################################################################
            #              COMMON PARAS
            #####################################################################
            # ====== CR-0814 START
            mID = "MID{}-{}".format(mKind.title(), GAME.getUniqueID())

            # chose mission location
            if "sLocID" in attr.keys():
                mSLocID = attr["sLocID"]
            else:
                # determine location from allowed location
                locPool = [x for x in starSys.locs.keys() if starSys.locs[x].mission]
                locPool = [x for x in locPool if starSys.locs[x].found or "rendezvous" in x.lower()]
                # if not locPool:
                #     renpy.say(None, "Unknown location error")
                mSLocID = random.choice(locPool)

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

            #####################################################################
            #              TRANSPORT
            #####################################################################
            if kind == "transport":    
                mName = "Transport" 

                # 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 x.ID not in starSys.getProhibited()]

                    wareID = random.choice(allWares)
                    if wareID == "ITMEternium":
                        amount  = random.randint(1,5)
                    wares = [wareID]* amount

                # chose reward
                sLoc = GAME.getSpaceLoc(mSLocID)
                mReward = int (amount * max(GAME.items[wareID].price*1.2, 220) * rewZoneFactors.get(sLoc.zone) * rewSysFactors.get(starSys.ID, 1.0)) 
                
                if wareID in GAME.getStarSys().getProhibited():
                    mReward = mReward * 2
                mCond = "GAME.ship.cargo.count(GAME.items['{}']) >= {}".format(wareID, amount)
                mReq = {} 
                mAttr = {"wareID": wareID, "amount": amount}
                mission = Mission(mID, mName, mKind, mStarSysID, mSLocID, mDue, mCond, mReq, mReward, mAttr)


            #####################################################################
            #              SMUGGLING
            #####################################################################
            elif kind == "smuggling":    
                mName = "Smuggling" 

                if GAME.logging:
                    logging.debug("rollMission: {}".format(attr.get("starSys", 0)))

                # 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(starSys.getProhibited())
                    wares = [wareID]* amount

                if GAME.logging:
                    logging.debug("rollMission: WareID {}".format(wareID))

                # chose reward
                sLoc = GAME.getSpaceLoc(mSLocID)
                mReward = int (amount * max(GAME.items[wareID].price*2.0, 1100) * rewZoneFactors.get(sLoc.zone) * rewSysFactors.get(starSys.ID, 1.0)) 

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

            #####################################################################
            #              BOUNTY
            #####################################################################
            elif kind == "bounty":
                if kind == "bounty":    
                    mName = "Bounty" 

                    # choose hostiles and level depending on star system
                    mLvl = lvl 

                    mProfiles = {
                        "SSIDIltari":
                            {1: ["hostile_1", "hostile_1a"],
                            2: ["hostile_2", "hostile_2a", "hostile_2b"],
                            3: ["hostile_3", "hostile_3a", "hostile_3b", "hostile_3c", "hostile_3d"  ],},
                        "SSIDArellarti":
                            {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"],},
                        "SSIDXenos":
                            {#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"],
                            6: ["hostile_6"],},
                        "SSIDQuthor":
                            {#1: ["hostile_1", "hostile_1a"],
                            #2: ["hostile_2", "hostile_2a", "hostile_2b"],
                            3: ["hostile_3", "hostile_3a", "hostile_3b", "hostile_3c", "hostile_3d"  ],
                            4: ["drengar_4" ],
                            5: ["drengar_5"],
                            6: ["drengar_6"],
                            7: ["drengar_7"],},
                        "SSIDNX010":
                            {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"],
                            6: ["hostile_6"],
                            7: ["hostile_7"],},
                            
                        }

                    if mStarSysID not in mProfiles.keys():
                        profiles = mProfiles["SSIDIltari"]
                    else:
                        profiles = mProfiles[mStarSysID]

                    minL = min(profiles.keys())
                    maxL = max(profiles.keys())
                    mLvl = capValue(mLvl, minL, maxL)
                    mProfile = random.choice(profiles[mLvl])

                    # chose reward
                    sLoc = GAME.getSpaceLoc(mSLocID)
                    mReward = int (2 * mLvl  * random.randint(20000,25000) * rewZoneFactors.get(sLoc.zone, 1.0)) 
                        
                    mCond = "False"
                    mReq = {} 
                    mAttr = {"mProfile": mProfile}
                    mission = Mission(mID, mName, mKind, mStarSysID, mSLocID, mDue, mCond, mReq, mReward, mAttr)

                    # Other settings 
                    mission.lvl = mLvl

            return(mission)


    class Mission():
        def __init__(self, ID, name, kind, starSysID, 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.starSysID = starSysID
            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		
#####################################################################


#####################################################################
#					MANAGEMENT		
#####################################################################    
screen mission_selector_scr(starSysOptions, mFilter):
    image "05_gui/mask 50.png"
    $ mStarSys = mStarSysOptions[0]
    $ missions = mStarSys.missions

    $ msg = "MISSIONS {}".format(mStarSys.name.upper())

    hbox pos 960, 85 xalign 0.5:
        frame xsize 50 ysize 40 yalign 0.5 background Solid("#ffffff00"): 
            image "05_gui/GUI arrow left.png" xalign 0.5 yalign 0.5 yoffset -3
            button action Return("left")
        text " "
        frame xsize 400 ysize 40 yalign 0.5 background Solid("#ffffff00"):
            text msg size FSIZE_LARGE outlines [ (absolute(5), "#0099cc", absolute(0), absolute(0)) ] yalign 0.5 xalign 0.5
        text " "
        frame xsize 50 ysize 40 yalign 0.5 background Solid("#ffffff00"): # CR-0257
            image "05_gui/GUI arrow right.png" xalign 0.5 yalign 0.5 yoffset -3 # CR-0257
            button action Return("right")
    key "K_LEFT" action Return("left")
    key "K_RIGHT" action Return("right")

    # filters 
    hbox ypos 145 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])    

    # formatting
    $ M_COLS = [20, 150, 300, 560, 1040, 1100, 1450, 1650]
    # missions
    side "c r":
        area 65,190,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 == "bounty":
                        $ C_B, C_E = C_OR_B, C_OR_E
                        $koff = 15
                    elif i.kind == "smuggling":
                        $ C_B, C_E = C_YE_B, C_YE_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

                            # kind
                            text "{}".format(C_B+i.name+ C_E) xpos M_COLS[0] yalign 0.5 size FSIZE

                            # starSys
                            if i.starSysID:
                                text "{}{}{}".format(C_B, GAME.starSys[i.starSysID].name, C_E) xpos M_COLS[1] yalign 0.5 size FSIZE
                                
                            # sLoc
                            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 M_COLS[2] yalign 0.5 size FSIZE
                            


                            # detail info
                            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 M_COLS[3] yalign 0.5 size FSIZE
                            elif i.kind == "bounty":
                                text C_B+"Difficulty Level {}".format(i.lvl)+C_E xpos M_COLS[3] yalign 0.5 size FSIZE

                            # credits
                            text C_GO_B+"{:,} Cr".format(i.reward)+C_GO_E xpos M_COLS[4] xalign 1.0 yalign 0.5 size FSIZE

                            # days left
                            text "Days Left: {}".format(dueDays) xpos M_COLS[5] yalign 0.5 size FSIZE # CR-0525

                            # fee
                            frame xsize 160 ysize 30 background Solid ("#0099ccff") yalign 0.5 xpos M_COLS[6]:
                                text "Fee {:,} Cr".format(int(i.reward*0.05)) xalign 0.5 yalign 0.5 size FSIZE_MED
                                button action Return(["sign",i])

                            # cargo check
                            if i.kind in ["transport", "smuggling"]:
                                $ itemID = i.attr["wareID"]
                                
                                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 M_COLS[7] yalign 0.5 size FSIZE_MED
                                else:
                                    text "{} Short".format(GAME.ship.cargoAssignable(i.attr["wareID"], i.attr["amount"], "delta")) xpos M_COLS[7] 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,990 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.955:
        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_15 
        call attr_mod(GAME.mc, "REP", -1, 0, 100, True) from _call_attr_mod_18
        $ 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_21        
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_3
        call transaction("Transport Rewards", mission.reward, True) from _call_transaction_7
        call attr_mod(GAME.mc,"REP", 1,30,100, True) from _call_attr_mod_19


    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_22        
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_4
        call transaction("Smuggling Rewards", mission.reward, True) from _call_transaction_8
        call attr_mod(GAME.mc,"NOT", 1,30,100, True) from _call_attr_mod_20
        $ 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_23        
        play sound "audio/success.wav"
        call find_notify(mission.reward, "MISSION REWARD") from _call_find_notify_5
        call transaction("Bounty Rewards", mission.reward, True) from _call_transaction_9
        call attr_mod(GAME.mc,"NOT", 1,50,100, True) from _call_attr_mod_21

        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()
