#!/usr/bin/python
# -*- coding: utf-8 -*-

LARGURA = 640
ALTURA = 480
FPS = 30
RAQ_ALTURA = 120

import pygame
from pygmeu import *
import random

class Bola(Sprite):
    def __init__(self, pai, nome, x, y, limites):
        Sprite.__init__(self, pai, nome, x, y)
        self.limites = limites
        self.imagem = pygame.Surface((20, 20)).convert_alpha()
        self.imagem.fill(pygame.Color(255, 255, 255))
        self.dx = 150
        self.dy = 150

    def atualizar(self, dt):
        Sprite.atualizar(self, dt)
        self.x += self.dx * dt / 1000
        self.y += self.dy * dt / 1000
        if self.y < self.limites.top:
            self.y += (self.limites.top - self.y)
            self.dy *= -1
        if self.y > self.limites.bottom:
            self.y -= (self.y - self.limites.bottom)
            self.dy *= -1
        if self.x < self.limites.left:
            Jogo.jogo.enviar_evento(msg='bateu_esq')
        if self.x > self.limites.right:
            Jogo.jogo.enviar_evento(msg='bateu_dir')


class Raquete(Sprite):
    def __init__(self, pai, nome, x, y, y_min, y_max, tecla_subir, tecla_descer):
        Sprite.__init__(self, pai, nome, x, y)
        self.y_min = y_min
        self.y_max = y_max
        self.tecla_subir = tecla_subir
        self.tecla_descer = tecla_descer
        self.dy = 300
        self.imagem = pygame.Surface((20, RAQ_ALTURA)).convert_alpha()
        self.imagem.fill(pygame.Color(255, 255, 255))


class RaqueteParada(EstadoSprite):
    def processar_evento(self, e):
        if e.type == pygame.KEYDOWN:
            if e.key == self.dono().tecla_descer:
                self.maquina_de_estados.avancar(RaqueteDescendo())
            elif e.key == self.dono().tecla_subir:
                self.maquina_de_estados.avancar(RaqueteSubindo())


class RaqueteSubindo(EstadoSprite):
    def atualizar(self, dt):
        raq = self.dono()
        ny = raq.y - raq.dy * dt / 1000
        if ny <= raq.y_min:
            ny = raq.y_min
            self.avancar(RaqueteParada())
        raq.y = ny

    def processar_evento(self, e):
        if e.type == pygame.KEYDOWN:
            if e.key == self.dono().tecla_descer:
                self.maquina_de_estados.avancar(RaqueteDescendo())
        elif e.type == pygame.KEYUP:
            if e.key == self.dono().tecla_subir:
                self.maquina_de_estados.avancar(RaqueteParada())


class RaqueteDescendo(EstadoSprite):
    def atualizar(self, dt):
        raq = self.dono()
        ny = raq.y + raq.dy * dt / 1000
        if ny >= raq.y_max:
            ny = raq.y_max
            self.avancar(RaqueteParada())
        raq.y = ny

    def processar_evento(self, e):
        if e.type == pygame.KEYDOWN:
            if e.key == self.dono().tecla_subir:
                self.maquina_de_estados.avancar(RaqueteSubindo())
        elif e.type == pygame.KEYUP:
            if e.key == self.dono().tecla_descer:
                self.maquina_de_estados.avancar(RaqueteParada())


class CenaPong(Cena):
    def __init__(self, pai, nome, largura, altura):
        Cena.__init__(self, pai, nome, largura, altura)
        Bola(self, 'bola', 0, 0, pygame.Rect(0, 0, largura, altura))
        Raquete(self, 'raq_esq', 40, 0, RAQ_ALTURA / 2, altura - RAQ_ALTURA / 2,
            pygame.K_w, pygame.K_s)
        Raquete(self, 'raq_dir', largura - 40, 0, RAQ_ALTURA / 2, altura - RAQ_ALTURA / 2,
            pygame.K_UP, pygame.K_DOWN)


class CenaPongEmJogo(EstadoSprite):
    def ao_entrar(self):
        cena = self.dono()
        bola = cena['bola']
        raq_esq = cena['raq_esq']
        raq_dir = cena['raq_dir']
        bola.x = cena.largura / 2
        bola.y = cena.altura / 2
        raq_esq.y = cena.altura /2
        raq_dir.y = cena.altura /2
        raq_esq.maquina_de_estados.avancar(RaqueteParada())
        raq_dir.maquina_de_estados.avancar(RaqueteParada())

    def processar_evento(self, e):
        if e.type == pygame.USEREVENT:
            if e.msg == 'bateu_esq' or e.msg == 'bateu_dir':
                self.avancar(CenaPongEmJogo())

    def atualizar(self, dt):
        cena = self.dono()
        bola = cena['bola']
        raq_esq = cena['raq_esq']
        raq_dir = cena['raq_dir']
        if bola.testar_colisao(raq_esq):
            bola.dx *= -1
            bola.x += 2 * (raq_esq.get_rect().right - bola.get_rect().left)
        if bola.testar_colisao(raq_dir):
            bola.dx *= -1
            bola.x -= 2 * (bola.get_rect().right - raq_dir.get_rect().left)


class Pong(Jogo):
    def __init__(self, nome, largura, altura, fps, titulo, flags=0):
        Jogo.__init__(self, nome, largura, altura, fps, titulo, flags)
        cena = CenaPong(self, 'cena', largura, altura)
        cena.maquina_de_estados.avancar(CenaPongEmJogo())

    def pintar(self, tela):
        tela.fill(pygame.Color(0, 0, 0))


def main():
    Pong('pong', LARGURA, ALTURA, FPS, 'Pong').executar()


if __name__ == "__main__":
    main()
