import re

import cargos

class NmlProps:
    def __init__(self, id_, mapping):
        self.id_ = id_
        self.mapping = mapping

    def __setitem__(self, key, val):
        self.mapping[key] = val

    def get(self, key, default=None):
        if key not in self.mapping or not self.mapping[key]:
            return default
        return self.mapping[key]

    def get_props(self, articulated=False, nogfx=False):

        def cc_bitmask(clss):
            if not clss or clss == ['NO_CARGO_CLASS']:
                return 'NO_CARGO_CLASS'
            out = []
            for cls in sorted(set(clss)):
                if not cls.startswith('CC_'):
                    cls = 'CC_' + cls
                out.append(cls)
            return 'bitmask({})'.format(', '.join(out))

        cargo_allow = re.findall(r'\b\w{4}\b',self.get('cargo_allow', ''))
        if cargo_allow:
            default_cargo = cargo_allow[0]
        else:
            default_cargo = 'DEFAULT_CARGO_FIRST_REFITTABLE'
        cargo_disallow = re.findall(
            r'\b\w{4}\b',self.get('cargo_disallow', ''))
        cc_allow = re.findall(r'\b\w+\b', self.get('cc_allow', ''))
        cc_disallow = re.findall(r'\b\w+\b', self.get('cc_disallow', ''))
        if not any([cargo_allow, cargo_disallow, cc_allow, cc_disallow]):
            cargo_allow = ['PASS']

        if self.get('long_name'):
            constants = re.findall(r'\bSTR_PUR_\w+', self.get('long_name'))
            if constants:
                xtra = ', ' + ', '.join(
                    ['string({})'.format(c) for c in constants])
            else:
                xtra = ''
            pur_str = 'string(STR_PUR_{}{})'.format(self.id_.upper(), xtra)
        else:
            pur_str = 'string(STR_NULL)'

        props = {
            'bitmask_vehicle_info': 0,
            'cargo_age_period': 185,
            'cargo_allow_refit': '[{}]'.format(
                ', '.join(sorted(set(cargo_allow)))),
            'cargo_capacity': 1,
            'cargo_disallow_refit': '[{}]'.format(
                ', '.join(sorted(set(cargo_disallow)))),
            'climates_available': 'NO_CLIMATE',
            'default_cargo_type': default_cargo,
            'length': 8,
            'loading_speed': self.get('loading_speed', 5),
            'misc_flags': 0,
            'name': pur_str,
            'non_refittable_cargo_classes': cc_bitmask(cc_disallow),
            'refit_cost': 0,
            'refittable_cargo_classes': cc_bitmask(cc_allow),
            'sprite_id': 'SPRITE_ID_NEW_TRAIN',
            'track_type': self.get('track_type', 'RAIL'),
            'visual_effect_and_powered': (
                'visual_effect_and_powered'
                '(VISUAL_EFFECT_DISABLE, 0, DISABLE_WAGON_POWER)'),
            }
        props['misc_flags'] = 'bitmask(TRAIN_FLAG_AUTOREFIT, TRAIN_FLAG_FLIP)'

        if articulated:
            return props.items()

        if self.get('engine_class'):
            engine_class = self.get('engine_class')
        elif self.get('type') == 'steam':
            engine_class = 'ENGINE_CLASS_STEAM'
        elif self.get('type') in {'electric', 'emu', 'metro'}:
            engine_class = 'ENGINE_CLASS_ELECTRIC'
        else:
            engine_class = 'ENGINE_CLASS_DIESEL'

        if nogfx:
            props['climates_available'] = 'NO_CLIMATE'
        else:
            props['climates_available'] = 'ALL_CLIMATES'

        props.update({
            'ai_special_flag': 0,
            'air_drag_coefficient': 0,
            'cost_factor': self.get('pur_cost', 0) \
                if not int(self.get('pur_cost', 0)) > 255 else 255,
            'dual_headed': 0,
            'engine_class': engine_class,
            'extra_power_per_wagon': 0,
            'extra_weight_per_wagon': 0,
            'introduction_date': 'date({},01,01)'.format(
                self.get('int_y', 0)),
            'model_life': self.get('model_life', 255) \
                if not self.get('model_life') == 'INF' else 255,
            'power': '{} hpM'.format(self.get('power', 0)),
            'reliability_decay': self.get('rel_decay', 20),
            'retire_early': 0,
            'running_cost_base': 'RUNNING_COST_STEAM',
            'running_cost_factor': self.get('run_cost', 0) \
                if not int(self.get('run_cost', 0)) > 255 else 255,
            'speed': '{} km/h'.format(self.get('speed', 0)),
            'tractive_effort_coefficient': self.get('te_coef', 0.3),
            'vehicle_life': self.get('vehicle_life', 255),
            'weight': '{} ton'.format(self.get('weight', 50))
            })
        return props.items()
