from OpenGL.GL import *
from OpenGL.GLU import *
import pygame, pygame.image
from pygame.locals import *

import random

import tubeMgr
import texMgr
import sound
import voiceover
import options

crateTex=-1
stickerTextures={}
cb_stickerTextures={}
numberTextures={}

EXIT_SPEED=40.0
crates=[]
exitingCrates=[]


def init(levelDesc):
    global gGameOver
    gGameOver = False

    global crates
    global exitingCrates
    crates=[]
    exitingCrates=[]
    
    global crateTex
    crateTex = texMgr.loadTexture("data/crate.png", "crate")

    stickerColors=["red", "yellow", "green", "blue"]
    
    for c in stickerColors:
        stickerTextures[c]=texMgr.loadTexture("data/sticker_%s.png"%c, "sticker_%s"%c)
        cb_stickerTextures[c]=texMgr.loadTexture("data/cb-sticker_%s.png"%c, "cb-sticker_%s"%c)

    for i in range(1,21):
        numberTextures[i]=texMgr.loadTexture("data/number_%02d_tex.png"%i, "number_%02d"%i)

    for i in levelDesc['crates'].keys():
        c=Crate(2*i)

        crateDesc=levelDesc['crates'][i]

        for colorDesc in crateDesc.split("/"):
            color, num=colorDesc.split(":")
            c.add_need(color, int(num))
        
        crates.append(c)


CRATEFUDGE = 4
LABEL_FUDGE_X = 8
LABEL_FUDGE_Y = 4

def drawCrates(board):
    for c in crates:
        c.draw(board)
    for c in exitingCrates:
        c.draw(board)
    


class Crate:
    def __init__(self, x):
        self.x=x
        self.needLabels=[]

        self.exiting=False
        self.exitOffset=0

    def add_need(self, label, num):
        self.needLabels.append((num, label))


    def update(self,dt):
        if self.exiting:
            self.exitOffset-=dt*EXIT_SPEED
        

    def draw(self, board):
        glBindTexture(GL_TEXTURE_2D, crateTex)
        left=self.x*board.scale+board.bufferX+CRATEFUDGE
        right=left+2*board.scale-2*CRATEFUDGE
    
        bottom=self.exitOffset
        top=bottom+2*board.scale-2*CRATEFUDGE

        glBegin(GL_QUADS)
        glTexCoord2f(0.0, 1.0); glVertex2f(  left, top)
        glTexCoord2f(1.0, 1.0); glVertex2f( right, top)
        glTexCoord2f(1.0, 0.0); glVertex2f( right, bottom)
        glTexCoord2f(0.0, 0.0); glVertex2f(  left, bottom)
        glEnd()


        glColor4f(1.0, 1.0, 1.0, 0.8)
        left += LABEL_FUDGE_X
        right -= LABEL_FUDGE_X
        middle = (bottom+top)/2.0
        midtop = (3*top+bottom)/4.0
        midbot = (top+3*bottom)/4.0
        midX=(left+right)/2.0
        stickH=top-bottom-2*LABEL_FUDGE_Y
        numleft=midX-stickH/2
        numright=midX+stickH/2

        if (len(self.needLabels)==2):
            num,label=self.needLabels[0]
            if options.g_color_assist:
                glBindTexture(GL_TEXTURE_2D, cb_stickerTextures[label])
            else:
                glBindTexture(GL_TEXTURE_2D, stickerTextures[label])
            glColor4f(1.0, 1.0, 1.0, 0.8)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  left, top-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( right, top-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( right, middle+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  left, middle+LABEL_FUDGE_Y)
            glEnd()

            glBindTexture(GL_TEXTURE_2D, numberTextures[num])
            glColor4f(1.0, 1.0, 1.0, 1.0)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  numleft, top-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( numright, top-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( numright, middle+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  numleft, middle+LABEL_FUDGE_Y)
            glEnd()
                          

            num,label=self.needLabels[1]
            if options.g_color_assist:
                glBindTexture(GL_TEXTURE_2D, cb_stickerTextures[label])
            else:
                glBindTexture(GL_TEXTURE_2D, stickerTextures[label])
            glColor4f(1.0, 1.0, 1.0, 0.8)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  left, middle-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( right, middle-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( right, bottom+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  left, bottom+LABEL_FUDGE_Y)
            glEnd()

            glBindTexture(GL_TEXTURE_2D, numberTextures[num])
            glColor4f(1.0, 1.0, 1.0, 1.0)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  numleft, middle-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( numright, middle-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( numright, bottom+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  numleft, bottom+LABEL_FUDGE_Y)
            glEnd()
            
        elif (len(self.needLabels)==1):
            num,label=self.needLabels[0]
            if options.g_color_assist:
                glBindTexture(GL_TEXTURE_2D, cb_stickerTextures[label])
            else:
                glBindTexture(GL_TEXTURE_2D, stickerTextures[label])
            
            glColor4f(1.0, 1.0, 1.0, 0.8)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  left, midtop-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( right, midtop-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( right, midbot+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  left, midbot+LABEL_FUDGE_Y)
            glEnd()

            glBindTexture(GL_TEXTURE_2D, numberTextures[num])
            glColor4f(1.0, 1.0, 1.0, 1.0)
            glBegin(GL_QUADS)
            glTexCoord2f(0.0, 1.0); glVertex2f(  numleft, midtop-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 1.0); glVertex2f( numright, midtop-LABEL_FUDGE_Y)
            glTexCoord2f(1.0, 0.0); glVertex2f( numright, midbot+LABEL_FUDGE_Y)
            glTexCoord2f(0.0, 0.0); glVertex2f(  numleft, midbot+LABEL_FUDGE_Y)
            glEnd()
            
            


        glColor4f(1.0, 1.0, 1.0, 1.0)

    def enterBall(self, b):
        if not self.needLabels:
            return

        bIsGood=False
        
        if b.color=='white':
            num,label=self.needLabels[0]
            self.needLabels[0]=(num-1,label)
            bIsGood=True
        elif b.color=='black':
            for i in range(len(self.needLabels)):
                num,label=self.needLabels[i]
                newNum=min(num+1,20)
                self.needLabels[i]=newNum,label
        else:
            for i in range(len(self.needLabels)):
                num,label=self.needLabels[i]
                if b.color==label:
                    self.needLabels[i]=(num-1,label)
                    bIsGood=True

        self.needLabels=[s for s in self.needLabels
                           if s[0]>0]

        if bIsGood:
            sound.play("plonk")
            voiceover.queue("short-good")
            
            return 1
        else:
            sound.play("clonk")
            voiceover.queue("short-bad")
            return 0
        
                         
                

        

                    
            
        
def enterBall(board, b):
    column=int((b.x-board.bufferX)/board.scale)

    for c in crates:
        if c.x==column or c.x+1==column:
            good=c.enterBall(b)
            if good == 1:
                return
            board.addMiss()
            
    

def update(dt):
    global crates

    for c in crates:
        if not c.needLabels:
            sound.play("cheer")
            exitingCrates.append(c)
            c.exiting=True

    crates=[c for c in crates if len(c.needLabels)>0]

    allOff=True
    for ec in exitingCrates:
        ec.update(dt)
        if ec.exitOffset>-100.0:
            allOff=False

    anyOn= not allOff

    return anyOn or len(crates)>0

def cheat(cheatNum):
    if cheatNum==1:
        b=tubeMgr.Ball("white")
        crates[0].enterBall(b)
