"""More ore from asteroids, and no credit junk in the ore crates."""
import re

from sc_lua import csv, strip_loot_entries

MOD = {
    'id': 'ore_drops',
    'name': 'More ore from mining asteroids',
    'description': 'Multiplies how much ore chunks spawn from a cracked asteroid in OW, plus removes credits from their loot table.',
    'author': 'Furebel',
    'default_enabled': True,
    'order': 20,
    'files': {
        'loot': 'data/gamedata/def/objects/ow_loot_tables.lua',
        'entities': 'data/gamedata/def/objects/openworld_entities.lua',
    },
    'tweakables': [
        {'key': 'multiplier', 'type': 'int', 'default': 5, 'min': 1, 'max': 20, 'step': 1,
         'label': 'Crates per mined asteroid (multiplier)',
         'help': '1 = vanilla. 5 = five times as many crates from every asteroid.'},
        {'key': 'strip_credits', 'type': 'bool', 'default': True,
         'label': 'Remove credit-only items from ore crates',
         'help': 'Uses the developers\' own "silver" comments to recognise credit items.'},
        {'key': 'ore_tables', 'type': 'text', 'default': 'OW3_OrePoor,OW3_OreNormal,OW3_OreRich,OW3_OreUltraRich',
         'advanced': True, 'label': 'Ore loot tables to clean (comma separated)', 'help': ''},
        {'key': 'exclude_crates', 'type': 'text', 'default': '', 'advanced': True,
         'label': 'Crates that must NOT be multiplied (comma separated)',
         'help': 'For example LootCrate_OW3_GoldNugget. Empty = multiply all.'},
    ],
}

BLOCK_START = re.compile(r'^\s*asteroid(?:_premium)?_loot_crate\s*=\s*\{')
ENTRY = re.compile(r'(\[\s*[\d.]+\s*\]\s*=\s*\{)([^{}]*)(\})')
STRING = re.compile(r'"([^"]+)"')


def multiply_crates(text, factor, exclude):
    lines = text.split('\n')
    depth, in_block, blocks, entries = 0, False, 0, 0
    for i, line in enumerate(lines):
        if not in_block and BLOCK_START.match(line):
            in_block, depth, blocks = True, 0, blocks + 1
        if in_block:
            code = line.split('--', 1)[0]

            def repl(m):
                crates = STRING.findall(m.group(2))
                if not crates:
                    return m.group(0)
                out = []
                for c in crates:
                    out.extend([c] * (1 if c in exclude else factor))
                return m.group(1) + ' ' + ', '.join('"%s"' % c for c in out) + ' ' + m.group(3)

            new, n = ENTRY.subn(repl, code)
            if n:
                lines[i] = new + line[len(code):]
                entries += n
            depth += code.count('{') - code.count('}')
            if depth <= 0:
                in_block = False
    return '\n'.join(lines), blocks, entries


def apply(files, v, log):
    if v['strip_credits']:
        files['loot'], report = strip_loot_entries(
            files['loot'], csv(v['ore_tables']), lambda line, item: 'серебр' in (line.split('--', 1) + [''])[1].lower())
        for name, r in report.items():
            log('%s: not found' % name if r is None else '%s: removed %d, %d left' % (name, r[0], r[1]))
    if v['multiplier'] > 1:
        files['entities'], blocks, entries = multiply_crates(files['entities'], v['multiplier'], set(csv(v['exclude_crates'])))
        log('asteroid crate lists multiplied by %d: %d blocks, %d lists' % (v['multiplier'], blocks, entries))
