# pygsear
# Copyright (C) 2003 Lee Harr
#
#
# This file is part of pygsear.
#
# pygsear is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# pygsear is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pygsear; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA


from pygsear.Drawable import Square, Multi
from pygsear.Util import color
from pygsear import conf

from conf import *

class NBlock(Square):
    def __init__(self, color):
        Square.__init__(self, side=SIZE, color=color)


class NShape(Multi):
    colors = {}

    def __init__(self):
        self.x = int(COLS / 2)
        self.x_old = self.x
        self.y = ROWS - 3

        Multi.__init__(self)

        # put the sprite offscreen until ready to use it.
        # otherwise, it will "flash" off to the side.
        # This is not really a fix, but it works...
        self.set_position(-100, -100)

        # calculate number of blocks in this shape
        n = 0
        for row in self.box:
            for col in row:
                if col:
                    n += 1

        rowlist = [tuple(row) for row in self.box]
        shape = tuple(rowlist)

        if self.colors.has_key(shape):
            c = self.colors[shape]
        else:
            c = color('random', 'medium')
            self.colors[shape] = c
        self.color = c

        for p in range(n):
            b = NBlock(c)
            self.addSprite(b)

        self.box_size = len(self.box)
        self.normalize()
        self.align()
        self.set_rcs()

    def align(self):
        """Make the sprites match the arrangement in self.box"""

        piece = 0
        xmax = ymax = 0
        sprites = self.innerSprites()
        box = self.box
        box_size = self.box_size
        for y in range(box_size):
            for x in range(box_size):
                if box[y][x]:
                    xmax = max(x, xmax)
                    ymax = max(y, ymax)
                    sprite = sprites[piece]
                    sprite.path.xOffset = x*SIZE
                    sprite.path.yOffset = -y*SIZE
                    piece += 1

        self.xmax = xmax
        self.move_x(0)
        self.ymax = ymax

    def normalize(self):
        """Push the shape to the lower left corner of self.box"""

        box = self.box
        box_size = self.box_size

        while box[0] == [0]*box_size:
            box.append(box.pop(0))

        left_edge = [r[0] for r in box]
        while left_edge == [0]*box_size:
            for r in box:
                r.append(r.pop(0))

            left_edge = [r[0] for r in box]

    def set_rcs(self):
        box = self.box
        box_size = self.box_size
        x = self.x
        x2 = x + box_size
        y = self.y
        rcs = []
        for rcount, r in enumerate(box):
            row = []
            for ccount in range(COLS):
                if ccount >= x and ccount < x+box_size:
                    #print ccount, x
                    if box[rcount][ccount-x]:
                        row.append(box[rcount][ccount-x])
                    else:
                        row.append(0)
                else:
                    row.append(0)
            rcs.append(row)

        self.rcs = rcs

    def move_x(self, x):
        self.x += x
        if self.x < 0:
            self.x = 0
        if self.x > COLS-self.xmax-1:
            self.x = COLS-self.xmax-1

    def move_left(self, ev=None):
        self.move_x(-1)

    def move_right(self, ev=None):
        self.move_x(1)

    def rotate_right(self, ev=None):
        box_size = self.box_size
        box = []

        for row in range(box_size):
            box.append([0]*box_size)

        for y in range(box_size):
            for x in range(box_size):
                box[y][x] = self.box[x][box_size-y-1]

        self.old_box = self.box
        self.box = box
        self.normalize()
        self.align()
        self.set_rcs()
        if not conf.game.nboard.fall_ok(self.y, self.rcs):
            self.box = self.old_box
            self.align()
            self.set_rcs()

    def rotate_left(self, ev=None):
        box_size = self.box_size
        box = []

        for row in range(box_size):
            box.append([0]*box_size)

        for y in range(box_size):
            for x in range(box_size):
                box[y][x] = self.box[box_size-x-1][y]

        self.old_box = self.box
        self.box = box
        self.normalize()
        self.align()
        self.set_rcs()
        if not conf.game.nboard.fall_ok(self.y, self.rcs):
            self.box = self.old_box
            self.align()
            self.set_rcs()

    def fall(self):
        self.y -= 1

    def cast_shadow(self):
        conf.game.draw_shadow(self.x, self.xmax+1)

    def move(self):
        self.set_rcs()
        if not conf.game.nboard.fall_ok(self.y, self.rcs):
            self.x = self.x_old
            self.align()
            self.set_rcs()
        self.x_old = self.x

        self.set_position((BLEFT+(self.x*SIZE), (ROWS-self.y-1)*SIZE))
        Multi.move(self)
        self.cast_shadow()


class N1Shape(NShape):
    box = [[1],]


class N2IShape(NShape):
    box = [[1, 1],
            [0, 0],]


class N3IShape(NShape):
    box = [[1, 1, 1],
            [0, 0, 0],
            [0, 0, 0],]


class N3LShape(NShape):
    box = [[1, 1],
            [1, 0],]


class N4IShape(NShape):
    box = [[1, 1, 1, 1],
            [0, 0, 0, 0],
            [0, 0, 0, 0],
            [0, 0, 0, 0],]


class N4LShape(NShape):
    box = [[1, 1, 1],
            [1, 0, 0],
            [0, 0, 0],]


class N4L2Shape(NShape):
    box = [[1, 1, 1],
            [0, 0, 1],
            [0, 0, 0],]


class N4TShape(NShape):
    box = [[1, 1, 1],
            [0, 1, 0],
            [0, 0, 0],]


class N4ZShape(NShape):
    box = [[0, 1, 1],
            [1, 1, 0],
            [0, 0, 0],]


class N4Z2Shape(NShape):
    box = [[1, 1, 0],
            [0, 1, 1],
            [0, 0, 0],]


class N4SShape(NShape):
    box = [[1, 1],
            [1, 1],]


class N5IShape(NShape):
    box = [[1, 1, 1, 1, 1],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],
            [0, 0, 0, 0, 0],]


class N5LShape(NShape):
    box = [[1, 1, 1, 1],
            [0, 0, 0, 1],
            [0, 0, 0, 0],
            [0, 0, 0, 0],]


class N5L2Shape(NShape):
    box = [[0, 1, 1, 1],
            [0, 0, 0, 1],
            [0, 0, 0, 1],
            [0, 0, 0, 0],]


class N5L3Shape(NShape):
    box = [[0, 0, 1, 1],
            [0, 0, 0, 1],
            [0, 0, 0, 1],
            [0, 0, 0, 1],]


class N5PlusShape(NShape):
    box = [[0, 1, 0],
            [1, 1, 1],
            [0, 1, 0],]


class N5ZigShape(NShape):
    box = [[1, 1, 0],
            [0, 1, 1],
            [0, 0, 1],]


class N5VShape(NShape):
    box = [[1, 0, 1],
            [1, 1, 1],
            [0, 0, 0],]
