# Combo counting.

import pygame

from listener import Listener
from constants import *

class AbstractCombo(Listener, pygame.sprite.Sprite):

  def __init__(self, playernum, game):
    pygame.sprite.Sprite.__init__(self)
    self._sticky = mainconfig['stickycombo']
    self._lowcombo = mainconfig['lowestcombo']
    self.combo = 0
    self._laststep = 0
    self._centerx = game.sprite_center + (game.player_offset * playernum)
    self._top = 320
    
    fonts = []
    for x in range(11, 0, -1):
      fonts.append(pygame.font.Font(None, 28+int(x*1.82)))

    # Store each digit individually, to avoid long text rendering
    # times in the middle of the game. FIXME: This breaks above 9999
    # combo currently; the PCR has code for the same trick that scales
    # infinitely.
    self._words = []
    for f in fonts:
      render = []
      for w in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'x COMBO']:
        img1 = f.render(w, 1, [16, 16, 16])
        img2 = f.render(w, 1, [224, 224, 224])
        img3 = pygame.Surface(img1.get_size())
        img3.blit(img1, [-2, 2])
        img3.blit(img1, [2, -2])
        img3.blit(img2, [0, 0])
        img3.set_colorkey(img3.get_at([0, 0]), RLEACCEL)
        render.append(img3)
      self._words.append(render)
    self._space = pygame.surface.Surface([0, 0])
    self.image = self._space

  def update(self, curtime):
    self._laststep = min(curtime, self._laststep)
    steptimediff = curtime - self._laststep

    if steptimediff < 0.36 or self._sticky:
      self._drawcount = self.combo
      drawsize = min(int(steptimediff * 50), len(self._words) - 1)
      if drawsize < 0: drawsize = 0
    else:
      self._drawcount = 0

    if self._drawcount >= self._lowcombo:
      render = self._words[drawsize]
      width = render[-1].get_width()
      thousands = self._drawcount / 1000
      hundreds = self._drawcount / 100
      tens = self._drawcount / 10
      ones = self._drawcount % 10
      if thousands:
        thousands = render[thousands % 10]
        width += thousands.get_width()      
      if hundreds:
        hundreds = render[hundreds % 10]
        width += hundreds.get_width()
      if tens:
        tens = render[tens % 10]
        width += tens.get_width()
      ones = render[ones]
      width += ones.get_width()
      height = render[-1].get_height()
      self.image = pygame.surface.Surface([width, height])
      self.image.set_colorkey(ones.get_at([0, 0]), RLEACCEL)
      left = 0		      
      if thousands:
        self.image.blit(thousands, [left, 0])
        left+= thousands.get_width()
      if hundreds:
        self.image.blit(hundreds, [left, 0])
        left += hundreds.get_width()
      if tens:
        self.image.blit(tens, [left, 0])
        left += tens.get_width()
      self.image.blit(ones, [left, 0])
      left += ones.get_width()
      r = self.image.blit(render[-1], [left, 0])
    else :
      self.image = self._space

    self.rect = self.image.get_rect()
    self.rect.top = self._top
    self.rect.centerx = self._centerx

# Breaks the combo on anything not a marvelous, perfect, or great.
class NormalCombo(AbstractCombo):
  def stepped(self, pid, dir, curtime, etime, rating, combo):
    if rating is None: return
    self._laststep = curtime
    self.combo += { "V": 1, "P": 1, "G": 1 }.get(rating, -self.combo)

# Breaks the combo on anything less than a great, but also doesn't
# increase it for great.
class OniCombo(AbstractCombo):
  def stepped(self, pid, dir, curtime, etime, rating, combo):
    if rating is None: return
    self._laststep = curtime
    self.combo += { "V": 1, "P": 1, "G": 0 }.get(rating, -self.combo)

# Pump It Up-style combo; okays add to your combo too.
class PumpCombo(AbstractCombo):
  def stepped(self, pid, dir, curtime, etime, rating, combo):
    if rating is None: return
    self._laststep = curtime
    self.combo += { "V": 1, "P": 1, "G": 1, "O": 1 }.get(rating, -self.combo)

combos = [NormalCombo, OniCombo, PumpCombo]
combo_opt = [
  (0, "Normal", "Greats or better increase a combo"),
  (1, "Oni-style", "Greats don't increase a combo, but also don't break it"),
  (2, "Pump It Up", "Okays or better increase a combo")]
