"Initialize the Levels module"

from __future__ import generators
import plus
import math
import string
import random

levels = []
currentLevels = []
currentIndex = 0

class Camera(object):
    def __init__(self, name, position):
        self.name = name
        self.position = position

    def apply(self):
        plus.setCameraPosition(self.position[0], self.position[1], self.position[2])

class StaticCamera(Camera):
    def __init__(self, name, position, rotation, fov):
        Camera.__init__(self, name, position)
        self.rotation = rotation
        self.fov = fov

    def apply(self):
        Camera.apply(self)
        plus.setCameraRotation(self.rotation[0], self.rotation[1])
        plus.setCameraFOV(self.fov)

class WatchCamera(Camera):
    def __init__(self, name, position, range):
        Camera.__init__(self, name, position)
        self.range = range

    def apply(self):
        Camera.apply(self)
        plus.setCameraFOVRange(self.range[0], self.range[1], self.range[2], self.range[3])

class SuperLevel(plus.Level):
    "Python base class of the C++ giLevel."
    name = "No Name"
    preview = "No Preview"
    in_list = True
    mission_index = 0
    
    def __init__(self):
        plus.Level.__init__(self)
        
        self.startpoint = (0, 0)
        self.startrotation = (0, 0, 0, 1)
        
        self.StaticCams = []
        self.StaticCamIterator = iter(self.StaticCams)
        self.currentStaticCam = None
        self.WatchCams = []
        self.WatchCamIterator = iter(self.WatchCams)
        self.currentWatchCam = None

    def AddStaticCamera(self, name, position, rotation, fov):
        self.StaticCams.append(StaticCamera(name, position, rotation, fov))

    def AddWatchCamera(self, name, position, range):
        self.WatchCams.append(WatchCamera(name, position, range))
        
    def NextStaticCamera(self):
        if len(self.StaticCams) > 0:
            try:
                self.currentStaticCam = self.StaticCamIterator.next()
            except StopIteration:
                self.StaticCamIterator = iter(self.StaticCams)
                self.currentStaticCam = self.StaticCamIterator.next()

            self.currentStaticCam.apply()

            return self.currentStaticCam.name
        else:
            return ""
            
    def LastStaticCamera(self):
        if self.currentStaticCam == None:
            return self.NextStaticCamera()
        else:
            self.currentStaticCam.apply()
            return self.currentStaticCam.name

    def NextWatchCamera(self):
        if len(self.WatchCams) > 0:
            try:
                self.currentWatchCam = self.WatchCamIterator.next()
            except StopIteration:
                self.WatchCamIterator = iter(self.WatchCams)
                self.currentWatchCam = self.WatchCamIterator.next()

            self.currentWatchCam.apply()
            
            return self.currentWatchCam.name
        else:
            return ""
            
    def LastWatchCamera(self):
        if self.currentWatchCam == None:
            return self.NextWatchCamera()
        else:
            self.currentWatchCam.apply()
            return self.currentWatchCam.name

    def NextAutoCamera(self):
        return ""
        
    def clearCameras(self):
        self.currentStaticCam = None
        self.currentWatchCam = None
        self.StaticCams = []
        self.WatchCams = []

def sortByIndex(x, y):
    if x.mission_index < y.mission_index:
        return -1
    elif x.mission_index > y.mission_index:
        return 1
    else:
        return 0
        
def sortByName(x, y):
    if x.name < y.name:
        return -1
    elif x.name > y.name:
        return 1
    else:
        return 0

def register(level):
    "Called by derived Levels to keep a master list of available level types."
    if issubclass(level, SuperLevel):
        extant = [x for x in levels if x.name == level.name]
        if len(extant) == 0:
            levels.append(level)

            print "We now have", len(levels), "levels!"

def enumAvailable():
    "Return a list of available levels via the C++ enumLevel function."
    list = [x for x in levels if x.in_list]
    list.sort(sortByIndex)
    for each in list:
        lev = plus.LevelDetail()
        lev.name = each.name
        lev.preview = each.preview
        lev.description = each.__doc__
        lev.id = id(each)

        plus.enumLevel(lev)

def createLevel(idnumber):
    "Call C++ setLevel for the level entry with this id."
    list = [x for x in levels if id(x) == idnumber]
    if len(list) > 0:
        print "Creating level", list[0].name
        global currentLevels
        newLevel = list[0]()
        currentLevels.append(newLevel)
        setLevel(newLevel, True)
        
        plus.setStartPoint(newLevel.startpoint)
        plus.setStartRotation(newLevel.startrotation)
        
        return currentLevels.index(newLevel)
    else:
        return -1

def createLevelByName(name):
    list = [x for x in levels if x.name == name]
    if len(list) > 0:
        print "Creating level", list[0].name
        global currentLevels
        newLevel = list[0]()
        currentLevels.append(newLevel)
        
        return currentLevels.index(newLevel)
    else:
        return -1

def setLevel(level, bDeleteOldLevel):
    global currentIndex
    global currentLevels
    currentIndex = currentLevels.index(level)
    plus.setLevel(level, bDeleteOldLevel)
    
def clearLevels():
    global currentLevels
    currentLevels = []