# Arup Guha
# 6/6/2024

'''
In this file we have the Token class rewritten to utilize a Pygame Rect
object. The main is the same as the previous main, we only needed to
make the change to the token class. This shows that data can be
encapsulated.
'''

import random
import math
import time
import pygame, sys
from pygame.locals import *

# Useful Constants
SCREEN_W = 1000
SCREEN_H = 600
BALL_D = 30
NUM_BALLS = 10

# Token Class we'll use for drawing objects in pyGame
class token:

    # Default settings.
    dx = 0
    dy = 0
    rec = None
    color = pygame.Color(0,0,255)

    # Constructor.
    def __init__(self,myx,myy,mydx,mydy,myside,mycolor):
        self.dx = mydx
        self.dy = mydy
        self.rec = pygame.Rect(myx, myy, myside, myside)
        self.color = mycolor

    # Call each frame.
    def move(self):
        self.rec.x += self.dx
        self.rec.y += self.dy

    # Executes updating dx as necessary for bouncing off the left wall.
    def bounceLeft(self):
        if self.rec.x + self.dx < 0:
            self.dx = -self.dx

    # Executes updating dx as necessary for bouncing off the right wall.
    def bounceRight(self, SCREEN_W):
        if self.rec.x + self.dx > SCREEN_W-self.rec.width:
            self.dx = -self.dx

    # Executes updating y as necessary for bouncing off the top wall.
    def bounceUp(self):
        if self.rec.y + self.dy < 0:
            self.dy = -self.dy

    # Executes updating y as necessary for bouncing off the bottom wall.
    def bounceDown(self, SCREEN_H):
        if self.rec.y + self.dy > SCREEN_H-self.rec.width:
            self.dy = -self.dy

    # Update for a single frame. Maybe this will typically be overridden.
    def updateFrame(self, DISPLAYSURF):
        self.move()
        self.bounceLeft()
        self.bounceRight(DISPLAYSURF.get_width())
        self.bounceUp()
        self.bounceDown(DISPLAYSURF.get_height())
        self.draw(DISPLAYSURF)

    # Draws this object on the display surface as a circle.
    # Likely to be overridden most of the time.
    def draw(self, DISPLAYSURF):
        pygame.draw.rect(DISPLAYSURF, self.color, self.rec, 0)

# This function handles moving each item listed in items.
def move(items):
    for item in items:
        item.move()

# Returns a random integer in between low and high not equal to 0.
def myrand(low,high):
    res = 0
    while res == 0:
        res = random.randint(low, high)
    return res

def main():

    # Basic Set Up
    pygame.init()
    DISPLAYSURF = pygame.display.set_mode((SCREEN_W, SCREEN_H))
    pygame.display.set_caption("Object Oriented Bouncing")
    WHITE = pygame.Color(255,255,255)
    BLUE = pygame.Color(0,0,255)
    clock = pygame.time.Clock()

    curT = time.time()

    # Make NUM_BALLS random tokens.
    mytokens = []
    for i in range(NUM_BALLS):

        # Somewhere on the screen.
        x = random.randint(1, SCREEN_W-BALL_D)
        y = random.randint(1, SCREEN_H-BALL_D)

        # Random non-zero movement in both directions.
        dx = myrand(-2,2)
        dy = myrand(-2,2)
        mytokens.append(token(x,y,dx,dy,BALL_D,BLUE))
        
    # Game loop.
    while True:

        # Look for events - we aren't using this right now.
        for event in pygame.event.get():
            
            if event.type == QUIT:
                pygame.quit()
                sys.exit()

        # White background.
        DISPLAYSURF.fill(WHITE)

        # Essentially update each ball.
        for item in mytokens:
            item.updateFrame(DISPLAYSURF)

        # Just testing collision code.
        for i in range(len(mytokens)):
            for j in range(i+1, len(mytokens)):
                if mytokens[i].rec.colliderect(mytokens[j].rec):
                    print("collide",i,j)
            
        # Update what we put on the canvas.
        pygame.display.update()

        # Wait a bit!
        clock.tick(100)

# Run it
main()
