import csv
import json


def mapType(creatureType):
    """
    maps the slayer's pit type to the foundry system type
    """
    switcher = {
        'Tiere': 'animal',
        'Humanoide': 'humanoid',
        'Konstrukte': 'construct',
        'Magische Wesen': 'magicalEntity',
        'Pflanzenwesen': 'plantBeing',
        'Untote': 'undead'
    }
    return switcher.get(creatureType)


def mapSize(size):
    """
    maps slayer's pits size to foundry system size
    """
    switcher = {
        'wi': 'tiny',
        'kl': 'small',
        'no': 'normal',
        'gr': 'large',
        'ri': 'huge',
        'ge': 'colossal'
    }
    return switcher.get(size)


def getAttributes(creature):
    """
    maps the attributes
    """
    return {
        "body": {
            "base": int(creature['KÖR']),
            "mod": 0
        },
        "mobility": {
            "base": int(creature['AGI']),
            "mod": 0
        },
        "mind": {
            "base": int(creature['GEI']),
            "mod": 0
        }
    }


def getTraits(creature):
    """
    maps the traits
    """
    return {
        "strength": {
            "base": int(creature['ST']),
            "mod": 0
        },
        "constitution": {
            "base": int(creature['HÄ']),
            "mod": 0
        },
        "agility": {
            "base": int(creature['BE']),
            "mod": 0
        },
        "dexterity": {
            "base": int(creature['GE']),
            "mod": 0
        },
        "intellect": {
            "base": int(creature['VE']),
            "mod": 0
        },
        "aura": {
            "base": int(creature['AU']),
            "mod": 0
        }
    }


def getCombatValues(creature):
    """
    maps combat values
    """
    magic = 0 if (creature['Zauber'] == '') else float(creature['Zauber'])
    targetMagic = 0 if creature['Zielzauber'] == '' else float(
        creature['Zielzauber'])
    return {
        "hitPoints": {
            "base": float(creature['Lebenskraft']),
            "mod": 0,
        },
        "defense": {
            "base": float(creature['Abwehr']),
            "mod": 0
        },
        "initiative": {
            "base": float(creature['Initiative']),
            "mod": 0
        },
        "movement": {
            "base": float(creature['Laufen']),
            "mod": 0
        },
        "meleeAttack": {
            "base": float(creature['Schlagen']),
            "mod": 0
        },
        "rangedAttack": {
            "base": float(creature['Schiessen']),
            "mod": 0
        },
        "spellcasting": {
            "base": magic,
            "mod": 0
        },
        "targetedSpellcasting": {
            "base": targetMagic,
            "mod": 0
        }
    }


def reformatCreature(creature):
    """
    reformats from table form into expected foundry style dict
    """

    size = mapSize(creature['GK'])
    creatureType = mapType(creature['Gruppe'])
    attributes = getAttributes(creature)
    traits = getTraits(creature)
    combatValues = getCombatValues(creature)

    description = creature['Waffen'] + '\n' + \
        creature['Panzerung'] + '\n' + creature['Talente']
    return {
        'name': creature['Name'],
        'type': 'creature',
        'data': {
            "attributes": attributes,
            "traits": traits,
            "combatValues": combatValues,
            "baseInfo": {
                "loot": "",
                "foeFactor": int(creature['GH']),
                "creatureType": creatureType,
                "sizeCategory": size,
                "experiencePoints": int(creature['EP']),
                "description": description
            }
        }
    }


def decode(filename, source):
    creatures = []
    npcs = []

    with open(filename, newline='\n') as csvFile:
        creatureReader = csv.DictReader(csvFile)
        for row in creatureReader:
            if row['Quelle'] == source:
                if row['Volk'] == '':
                    creatures.append(row)
                else:
                    npcs.append(row)

    return (creatures, npcs)


creatures, npcs = decode('Bestiarium.csv', 'Dungeonslayers Basisbox')

with open('bestiarium.json', 'w') as outfile:
    mappedCreatures = list(map(reformatCreature, creatures))
    json.dump(mappedCreatures, outfile)