import global_vars as g

class Block:
    pass

class ReturnBlock(Block):
    pass

class Rval:
    """
    Container class to hold to the return value of block.
    Required to unify the behaviour of replacing return values in
    blocks.
    """
    def __init__(self, val):
        self.val = val
    def __str__(self):
        return str(self.val)

class SpriteGroup(ReturnBlock):
    def __init__(self, name, loading, loaded):
        self.name = name
        self.loading = [Rval(l) for l in loading]
        self.loaded = [Rval(l) for l in loaded]
    @property
    def rvals(self):
        for v in self.loading + self.loaded:
            yield v
    def __str__(self):
        return self.name
    def output(self):
        return (
            'spritegroup {name} {{\n'
            '{ind}loading: [{loading}];\n'
            '{ind}loaded: [{loaded}]; }}'.format(
                name=self.name, ind=g.ind,
                loading=', '.join([str(v) for v in self.loading]),
                loaded=', '.join([str(v) for v in self.loaded]))
            )

class SpriteSet(Block):
    def __init__(self, name, png, type_, flipped=False, depot=False):
        self.name = name
        self.png = png
        self.type_ = type_
        self.flipped = flipped
        self.depot = depot
    def __str__(self):
        return self.name
    def output(self):
        return (
            'spriteset ({name}, "{png}") {{\n'
            '{tmpl} }}'.format(
                name=self.name, png=self.png,
                tmpl=get_tmpl(self.type_, self.flipped, self.depot))
            )

class Switch(ReturnBlock):
    def __init__(self, name, range_vals, scope="SELF", var=None):
        self.name = name
        self.range_vals = [(r, Rval(v)) for r, v in range_vals]
        self.scope = scope
        if not var:
            self.type_ = 'random_switch'
            self.var = ''
        else:
            self.type_ = 'switch'
            self.var = ', {}'.format(var)
    @property
    def rvals(self):
        for v in self.range_vals:
            yield v[1]
    def __str__(self):
        return self.name
    def output(self):
        return (
            '{type_} (FEAT_TRAINS, {scope}, {name}{var}) {{\n'
            '{xprs} }}'.format(
                type_=self.type_, scope=self.scope,
                name=self.name, var=self.var,
                xprs = '\n'.join(
                    ['{}{}: {};'.format(g.ind, r, v) \
                     for r, v in sorted(self.range_vals, key=lambda x: x[0])]))
            )

def get_tmpl(length, flipped, depot=False):
    def gen(skew):
        an = 'NOANIM' if 'noanim' in g.cmd else 'ANIM'
        tmpl_base = [
            [0,   0, 20, 40, -9,  -24, an],
            [20,  0, 40, 40, -27, -27, an],
            [60,  0, 50, 40, -29, -31, an],
            [110, 0, 40, 40, -19, -27, an],
            [150, 0, 20, 40, -9,  -22, an],
            [170, 0, 40, 40, -19, -27, an],
            [210, 0, 50, 40, -21, -31, an],
            [260, 0, 40, 40, -11, -27, an]
        ]
        out = []
        for (line, s) in zip(tmpl_base, skew):
            line[4] += s[0]
            line[5] += s[1]
            out.append(line)
        return '\n'.join(['{}[{}]'.format(
            g.ind, ', '.join([str(i) for i in l])) for l in out])

    if length == 'pur':
        return '{}[210, 0, 50, 40, -22, -31]'.format(g.ind)
    if length == 'pur_separate':
        return '{}[6, 49, 80, 16, -17, -12]'.format(g.ind)

    f = 8 - int(length)
    if int(length) > 8:
    #[0,   0, 20, 40, -9,        -24+2*LEN]
    #[20,  0, 40, 40, -27-4*LEN, -27+LEN]
    #[60,  0, 50, 40, -29-8*LEN, -31]
    #[110, 0, 40, 40, -19-4*LEN, -27-2*LEN]
    #[150, 0, 20, 40, -9,  -22-5*LEN]
    #[170, 0, 40, 40, -19+4*LEN, -27-2*LEN]
    #[210, 0, 50, 40, -21+8*LEN, -31]
    #[260, 0, 40, 40, -11+4*LEN, -27+LEN]
        if not depot:
            skew = ((0,  2*f), (-4*f, f   ), (-8*f, 0), (-4*f, -2*f),
                    (0, -5*f), ( 4*f, -2*f), ( 8*f, 0), ( 4*f,    f))
        else:
            skew = ((0,  2*f), (-4*f, f   ), (-8*f, 0), (-4*f, -2*f),
                    (0, -5*f), ( 4*f, -2*f), ( 0,   0), ( 4*f,    f))
    elif flipped:
        skew = ((0,  f  ), (-2*f,  0), (-4*f, 0), (-2*f, -f),
                (0, -4*f), ( 2*f, -f), ( 4*f, 0), ( 2*f,  0))
    else:
        skew = ((0, -2*f), (0, -f), (0, 0), (0,  0),
                (0,   -f), (0,  0), (0, 0), (0, -f))
    return gen(skew)
