############################################
######### DashPanel extra data app #########
#     Credits: Based on Spartens work #
############################################
import os
import ac
import sys
import mmap
import acsys
import struct
import os.path
import platform

# import libraries
if platform.architecture()[0] == "64bit":
	sysdir = os.path.dirname(__file__) + '/stdlib64'
else:
	sysdir = os.path.dirname(__file__) + '/stdlib'

sys.path.insert(0, sysdir)
os.environ['PATH'] = os.environ['PATH'] + ";."

import ctypes
from ctypes import c_float, c_char, c_int32

#define structures
class vec3(ctypes.Structure):
	_pack_ = 4
	_fields_ = [('x', c_float),
		('y', c_float),
		('z', c_float),]

class acsVehicleInfo(ctypes.Structure):
	_pack_ = 4
	_fields_ = [('carId', c_int32),
		('driverName', c_char * 64),
		('bestLapMS', c_int32),
		('lapCount', c_int32),
		('lastLapTimeMS', c_int32),
		('worldPosition', vec3),
		('isCarInPitline', c_int32),
		('isCarInPit', c_int32),
		('carLeaderboardPosition', c_int32),
		('carRealTimeLeaderboardPosition', c_int32),
		('spLineLength', c_float),
		('isConnected', c_int32)]

class DPSharedMemory(ctypes.Structure):
	_pack_ = 4
	_fields_ = [('version', c_int32),
		('numVehicles', c_int32),
		('vehicleInfo', acsVehicleInfo * 64)]

class DPSharedMem:
	def __init__(self):
		self._acpmf_dashpanel = mmap.mmap(0, ctypes.sizeof(DPSharedMemory),"acpmf_dashpanel")
		self.dpData = DPSharedMemory.from_buffer(self._acpmf_dashpanel)

	def close(self):
		self._acpmf_dashpanel.close()

	def __del__(self):
		self.close()

	def getsharedmem(self):
		return self.dpData

sharedMem = DPSharedMem()

def acMain(ac_version):
	appWindow = ac.newApp("DashPanel")
	ac.setSize(appWindow, 400, 80)

	ac.log("DashPanel extra data application started")
	msg = ac.addLabel(appWindow, "This application shares extra data with DashPanel.")
	ac.setPosition(msg,3,30)
	msg2 = ac.addLabel(appWindow, "There is no need to keep this app window open.")
	ac.setPosition(msg2,3,50)

	return "DashPanel"

def updateSharedMemory():
	global sharedMem
	dpDataShare = sharedMem.getsharedmem()
	dpDataShare.version = 1
	dpDataShare.numVehicles = ac.getCarsCount()
	#ac.console("numVehicles: " + str(dpDataShare.numVehicles))
	
	#now we'll build the slots, so we later know every single (possible) car
	carIds = range(0, ac.getCarsCount(), 1)
	for carId in carIds:
		#first we'll check wether there is a car for this id; as soon it
		#returns -1
		#it's over
		if str(ac.getCarName(carId)) == '-1':
			break 			
		else:
			dpDataShare.vehicleInfo[carId].carId = carId
			dpDataShare.vehicleInfo[carId].driverName = ac.getDriverName(carId).encode('utf-8')
			dpDataShare.vehicleInfo[carId].bestLapMS = ac.getCarState(carId, acsys.CS.BestLap)
			dpDataShare.vehicleInfo[carId].lapCount = ac.getCarState(carId, acsys.CS.LapCount)
			dpDataShare.vehicleInfo[carId].lastLapTimeMS = ac.getCarState(carId, acsys.CS.LastLap)
			dpDataShare.vehicleInfo[carId].worldPosition = ac.getCarState(carId, acsys.CS.WorldPosition)
			dpDataShare.vehicleInfo[carId].isCarInPitline = ac.isCarInPitline(carId)
			dpDataShare.vehicleInfo[carId].isCarInPit = ac.isCarInPit(carId)
			dpDataShare.vehicleInfo[carId].carLeaderboardPosition = ac.getCarLeaderboardPosition(carId)
			dpDataShare.vehicleInfo[carId].carRealTimeLeaderboardPosition = ac.getCarRealTimeLeaderboardPosition(carId)
			dpDataShare.vehicleInfo[carId].spLineLength = ac.getCarState(carId, acsys.CS.NormalizedSplinePosition)
			dpDataShare.vehicleInfo[carId].isConnected = ac.isConnected(carId)

timer = 0
def acUpdate(deltaT):
  global timer
  timer += deltaT
  #if timer > 0.025:
  if timer > 0.033:
	  updateSharedMemory()
	  timer = 0

def acShutdown():
	global sharedMem
	sharedMem.close()
	ac.log("DashPanel app shutting down.")
