# GPLv3-or-later
# (C) J.Y.Amihud ( blenderdumbass )

# This will deal with garage and inventory system.

import bge

import mathutils

from Scripts import Reuse

from Scripts import Vehicle
from Scripts import Money
from Scripts import Hints

from Scripts.Common import *

if "inventory" not in bge.logic.globalDict:
    bge.logic.globalDict["inventory"] = {}
inventory = bge.logic.globalDict["inventory"]

# Items you can buy for the inventory
shop = {
    "Wheels":{
        "name":"Car Wheels",
        "cost":392,
        "model":"Garage_wheel",
        "icon":[0,1],
        "usemodel":"HatchBack01-white-wheel",
        "usescale":0.383585
    },
    "Parts":{
        "name":"Body-work\nParts Kit",
        "cost":283,
        "model":"Garage_bodypart",
        "icon":[0,2],
        "usemodel":"Redkiss_Car_body.005"
    },
    "Nitros":{
        "name":"NiTRO",
        "cost":465,
        "model":"Garage_Nitro",
        "icon":[0,0],
        "usemodel":"NitroCan"
    },
    "Spoiler1":{
        
        "name":"Smooth-Bruh\nSpoiler",
        "cost":249,
        "model":"Garage_Spoiler1",
        "icon":[0,3],
        "usemodel":"Spoiler1_Attatch",
        "effects":{
            "drag"     :0.75,
            "downforce":1.3            
        }
    },
    "Spoiler2":{
        
        "name":"Metalcore\nSpoiler",
        "cost":353,
        "model":"Garage_Spoiler2",
        "icon":[0,4],
        "usemodel":"Spoiler2_Attatch",
        "effects":{
            "drag"     :0.50,
            "downforce":1.51            
        }
    },
    "Spoiler3":{
        
        "name":"Stupid\nSpoiler",
        "cost":481,
        "model":"Garage_Spoiler3",
        "icon":[0,5],
        "usemodel":"Spoiler3_Attatch",
        "effects":{
            "drag"     :0.90,
            "downforce":1.05            
        }
    },
    "Spoiler4":{
        
        "name":"6C\nSpoiler",
        "cost":699,
        "model":"Garage_Spoiler4",
        "icon":[0,6],
        "usemodel":"Spoiler4_Attatch",
        "effects":{
            "drag"     :0.3,
            "downforce":2.01            
        }
    }
}


def Encode():

    # We want to look through all cars that are in the garage.
    # And see which ones are in the garage

    scene = bge.logic.getCurrentScene()
    dani = scene.objects["Dani_Box"]
    garage = scene.objects["GarageColider"]
    garageDistance = 31

    # Making sure that we are not running it forever
    saved = bge.logic.globalDict.get("garage-saved", [])
    if saved:
        return saved

    # Saving the cars.

    # IMPORTANT! The data here should be possible to save into json.
    
    for car in bge.logic.globalDict["allcars"]:
        if car.getDistanceTo(garage) < garageDistance:

            cardata = Vehicle.Encode(car)
            saved.append(cardata)
            Reuse.Delete(car)

    bge.logic.globalDict["garage-saved"] = saved
    return saved

def Decode():

    # This will restore cars into the garage
    
    scene = bge.logic.getCurrentScene()
    dani = scene.objects["Dani_Box"]
    garage = scene.objects["GarageColider"]

    # Making sure that we are not running it forever
    saved = bge.logic.globalDict.get("garage-saved", [])
    if not saved:
        return

    for cardata in saved:

        Vehicle.Decode(cardata, new=True)

    bge.logic.globalDict["garage-saved"] = []
    UpdateShelfs()

def Inside():

    scene = bge.logic.getCurrentScene()
    dani = scene.objects["Dani_Box"]
    garage = scene.objects["GarageColider"]
    garageDistance = 31

    ingarage = []
    
    for car in bge.logic.globalDict["allcars"]:
        if car.getDistanceTo(garage) < garageDistance:
            ingarage.append(car)

    return ingarage


def Computer():

    # The inventory computer in the Garage

    scene = bge.logic.getCurrentScene()
    cont = bge.logic.getCurrentController()
    dani = scene.objects["Dani_Box"]
    
    computer           = scene.objects["Computer"]
    computerIcon       = scene.objects["ComputerIcon"]
    computerIconTop    = scene.objects["ComputerIcon.Top"]
    computerIconBottom = scene.objects["ComputerIcon.Bottom"]
    computerItemName   = scene.objects["Garage_Computer_Text.Name"]
    computerItemHave   = scene.objects["Garage_Computer_Text.Have"]
    computerItemPrice  = scene.objects["Garage_Computer_Text.Price"]

    keys = bge.logic.globalDict["keys"]
    
    if dani.getDistanceTo(computer) > 3:
        return

    else:

        # Updating the icons

        # You need to trigger the depsgraph on them for them
        # to get the material updated. So we do a dummy operation.

        Hints.Show("garage computer",
                   "[Parts eShop]\n[Up], [Down] to choose.\n[Enter] to buy.",
                   (-756.137,
                    -1048.46,
                    407.162))
        
        computerIcon.applyRotation((0,0,0))
        computerIconTop.applyRotation((0,0,0))
        computerIconBottom.applyRotation((0,0,0))
                
        for n, name in enumerate(shop):
            item = shop[name]
            have = inventory.get(name, 0)

            if computer.get("selection",0) == n:

                printname = item.get("name", name)
                computerItemName["Text"] = printname

                have = "have "+str(int(inventory.get(name, 0)))
                computerItemHave["Text"] = have

                price = "$"+str(item.get("cost", 0))
                computerItemPrice["Text"] = price
                

                
                icon      = item.get("icon", [16,16])
                computerIcon.blenderObject["raw"]    = icon[0]
                computerIcon.blenderObject["column"] = icon[1]
                
            elif computer.get("selection",0) + 1 ==  n:

                icon      = item.get("icon", [16,16])
                computerIconBottom.blenderObject["raw"]    = icon[0]
                computerIconBottom.blenderObject["column"] = icon[1]

            elif computer.get("selection",0) + 1 ==  len(shop):

                icon      = [15,15]
                computerIconBottom.blenderObject["raw"]    = icon[0]
                computerIconBottom.blenderObject["column"] = icon[1]

            elif computer.get("selection",0) - 1 == n:

                icon      = item.get("icon", [16,16])
                computerIconTop.blenderObject["raw"]    = icon[0]
                computerIconTop.blenderObject["column"] = icon[1]

            elif computer.get("selection",0) == 0:

                icon      = [15,15]
                computerIconTop.blenderObject["raw"]    = icon[0]
                computerIconTop.blenderObject["column"] = icon[1]
                
            

        if keycodes["UpArrow"] in keys and not computer.get("timer"):
            computer["selection"] = max(computer.get("selection",0) - 1, 0)
            computer["timer"] = 5
            
        elif keycodes["DownArrow"] in keys and not computer.get("timer"):
            computer["selection"] = min(computer.get("selection",0) + 1, len(shop)-1)
            computer["timer"] = 5

        elif keycodes["Enter"] in keys and not computer.get("timer"):
            Buy(list(shop.keys())[computer.get("selection",0)])
            computer["timer"] = 5
            
        if computer.get("timer"): computer["timer"] -= 1

def Buy(name):

    # This function will execute a buying of an item

    # First we are going to test whether the player has enough money
    cost  = shop.get(name, {}).get('cost', 0)
    model = shop.get(name, {}).get('model')
    
    if Money.Have(cost):

        Money.Pay(cost)

        if name not in inventory:
            inventory[name] = 1
        else:
            inventory[name] += 1

        UpdateShelfs()
        
    else:
        bge.logic.globalDict["print"] = "Not enough Money to buy "+name+"."

def Use(name):

    if name in inventory:
        inventory[name] = max(inventory[name] - 1, 0)
    UpdateShelfs()

def Has(name):

    return inventory.get(name)
   
def UpdateShelfs():

    # This function updates the shelfs in the game to show if you
    # have stuff. Otherwise you would need to come every time to the
    # computer.

    scene = bge.logic.getCurrentScene()

    for name in inventory:

        model  = shop.get(name, {}).get('model')
        amount = inventory[name]
        amount = min( amount, 5 )
        
        if model:
            
            model = scene.objects[model]
            model.blenderObject.modifiers["Array"].count = amount
            if not amount:
                model.visible = False
            else:
                model.visible = True