# 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


import random

import pygame
from pygame.locals import K_UP, K_LEFT, K_RIGHT, K_DOWN, K_s, K_p

from pygsear.Game import Game
from pygsear.Drawable import Square, Multi, Image, Stationary
from pygsear.Event import KEY_Event, Repeat_KEY_Event
from pygsear.Util import color
from pygsear.Widget import Score
from pygsear import conf

import Shape
import Board
import Level
from conf import *

WHITE = color('white')
BLACK = color('black')
RED = color('red')


class NGame(Game):
    splash_filename = None
    def initialize(self):
        self.ticks = TICKS
        self.tock = TICKS

        self.set_title('ntris')

        self.nboard = Board.NBoard()
        self.nboard.set_position(BLEFT, ROWS*SIZE)
        self.sprites.add(self.nboard)
        self.decorate_board()

        self._shadow = True

        self.controls = self.addEventGroup()

        self.level = Level.Level()

        self.shape_types = self.level.shape_types

        self.score = Score(position=(550, 15), text="Score:")
        self.lines = Score(position=(550, 75), text="Lines:")
        self.levels = Score(position=(550, 135), text="Level:")
        self.sprites.add(self.score)
        self.sprites.add(self.lines)
        self.sprites.add(self.levels)

        self.score_mult = 1

        self.new_piece()

        self.connect_controls()
        self.events.add(KEY_Event(key=K_DOWN, on_press=self.drop_piece))
        self.events.add(KEY_Event(key=K_s, on_press=self.toggle_shadow))
        self.events.add(KEY_Event(key=K_p, on_press=self.pause_game))

    def connect_controls(self):
        c = self.controls
        c.kill()
        e = self.events
        b = self.shape

        ku = KEY_Event(key=K_UP, on_press=b.rotate_left)
        kl = Repeat_KEY_Event(key=K_LEFT, on_hold=b.move_left)
        kr = Repeat_KEY_Event(key=K_RIGHT, on_hold=b.move_right)

        e.add(ku)
        e.add(kl)
        e.add(kr)

        c.add(ku)
        c.add(kl)
        c.add(kr)

    def decorate_board(self):
        bg = self.window.bg
        pygame.draw.line(bg, WHITE, (BLEFT-2, 0), (BLEFT-2, ROWS*SIZE))
        pygame.draw.line(bg, WHITE, (BLEFT-2, ROWS*SIZE), (BRIGHT+2, ROWS*SIZE))
        pygame.draw.line(bg, WHITE, (BRIGHT+2, ROWS*SIZE), (BRIGHT+2, 0))

        logo = Image(filename='ntris_logo.png')
        slogo = Stationary(sprite=logo)
        slogo.set_position((525, 250))

        name = Image(filename='ntris_name.png')
        sname = Stationary(sprite=name)
        sname.set_position((17, 85))

        pygame.display.update()

    def pause_game(self, ev=None):
        self.waitFor()

    def toggle_shadow(self, ev):
        self._shadow = not self._shadow
        if not self._shadow:
            self.erase_shadow()

    def erase_shadow(self):
        pygame.draw.line(self.window.bg, BLACK, (BLEFT, (ROWS*SIZE)+4), (BRIGHT, (ROWS*SIZE)+4))
        pygame.draw.line(self.window.screen, BLACK, (BLEFT, (ROWS*SIZE)+4), (BRIGHT, (ROWS*SIZE)+4))
        pygame.display.update(((BLEFT, (ROWS*SIZE)+4), (ROWS*SIZE, 1)))

    def draw_shadow(self, x, width):
        if self._shadow:
            self.erase_shadow()
            pygame.draw.line(self.window.bg, RED, (BLEFT+(x*SIZE), (ROWS*SIZE)+4), (BLEFT+((x+width)*SIZE), (ROWS*SIZE)+4))
            pygame.draw.line(self.window.screen, RED, (BLEFT+(x*SIZE), (ROWS*SIZE)+4), (BLEFT+((x+width)*SIZE), (ROWS*SIZE)+4))
            pygame.display.update(((BLEFT, (ROWS*SIZE)+4), (ROWS*SIZE, 1)))
            #pygame.display.update()

    def drop_piece(self, ev=None):
        y = self.shape.y
        rcs = self.shape.rcs

        self.score_mult = 1
        while self.nboard.fall_ok(y-1, rcs):
            self.score_mult += 1
            self.shape.fall()
            y -= 1

        self.shape.kill()
        self.freeze_piece()
        self.new_piece()

    def freeze_piece(self):
        level = self.level
        y = self.shape.y
        rcs = self.shape.rcs

        size = self.nboard.freeze_piece(self.shape, y-1, rcs)
        piece_points = (level.level+1) * size
        self.score.addPoints(piece_points)
        level.score += piece_points

        nrows = self.nboard.remove_full_rows()
        row_points = self.score_mult * nrows**2
        self.score.addPoints(row_points)
        level.score += row_points
        self.score_mult = 1
        self.score.updateScore()

        if nrows:
            self.lines.addPoints(nrows)
            self.lines.updateScore()
            level.lines += nrows

        if level.lines >= level.next_lines or level.score >= level.next_score:
            level.next()
            self.shape_types = level.shape_types
            self.ticks = level.ticks
            self.levels.addPoints(1)
            self.levels.updateScore()

    def new_piece(self):
        shape_type = random.choice(self.shape_types)

        b = shape_type()
        b.center(y=SIZE)
        self.sprites.add(b)
        self.shape = b
        self.connect_controls()
        if not self.nboard.fall_ok(self.shape.y-1, self.shape.rcs):
            self.stop = 1

    def checkCollisions(self):
        level = self.level

        ticks = conf.ticks
        self.tock -= ticks
        if self.tock < 0:
            self.tock = self.ticks

            y = self.shape.y
            rcs = self.shape.rcs

            if self.nboard.fall_ok(y-1, rcs):
                self.shape.fall()
            else:
                self.shape.kill()
                self.freeze_piece()
                self.new_piece()





if __name__ == '__main__':
    g = NGame()
    g.mainloop()


