# written by: Rylan Uherek, Avinash Oza, Mozam Todiwala, Pintu Patel, Mandeep Desai
# tested by: Rylan Uherek, Avinash Oza, Mozam Todiwala, Pintu Patel, Mandeep Desai
# debugged by: Rylan Uherek, Avinash Oza, Mozam Todiwala, Pintu Patel, Mandeep Desai

from django.db import models
from django.contrib.auth.models import User
from virtualstockmarket.SecurityInfo import *

class League (models.Model): 
	
	league_name = models.CharField(max_length=40, db_column='LeagueName')
	private = models.BooleanField(null=False, blank=False, db_column='Private') # is the league private or not
	start_date = models.DateTimeField(db_column='StartDate')
	end_date = models.DateTimeField(db_column='EndDate')
	
	starting_balance = models.DecimalField(max_digits=15, decimal_places=2, db_column='StartingBalance')
	league_password = models.CharField(blank = True, max_length=30, db_column='LeaguePassword')
	league_admin = models.ForeignKey(User, blank=True, related_name = 'LeagueAdmin')

	class Meta:
		verbose_name = 'League'

	def __str__(self):
		return ('%s' % self.league_name)


class LeagueUser(models.Model):

	user_name = models.ForeignKey(User, blank=True, related_name = 'UserName')
	cash_balance = models.DecimalField (max_digits=12, decimal_places=2, db_column = 'CashBalance')
	current_value = models.DecimalField(max_digits=8, decimal_places=2, db_column = 'CurrentValue') #current value of the users portfolio in a league
	user_league = models.ForeignKey(League, blank=True, related_name = 'UserLeagueLU') #the league the user is in

	class Meta:
		verbose_name = 'League User'

	def __str__(self):
		return ('%s - %s' % (self.user_league.league_name, self.user_name))

	# function to update the value of a LeagueUser object
	def updateValue(self):
		# find all of the assets the user holds for the given portfolio
		entries = PortfolioEntry.objects.filter(user_name=self).filter(open=True).filter(user_league=self.user_league)

		totalvalue = float(self.cash_balance)

		# get the current price of each entry
		for entry in entries:
			ticker = entry.ticker_symbol
			
			# get the market price of the entry
			marketdata = s_get_all_data(ticker)
			marketprice = float(marketdata['price'])

			totalvalue += marketprice

		self.current_value = totalvalue

#Models related to TicketEntry and PortfolioEntry based on Entry base class

#Define a default Entry 
class Entry(models.Model):

        ticker_symbol = models.CharField (max_length=8, db_column='TickerSymbol')
        quantity = models.DecimalField(max_digits=5, decimal_places = 0, db_column = 'Quantity')
        
	class Meta:
		abstract = True

class TicketEntry(Entry):

	DURATION = (
	('DAY' , 'Day Order'),
	('GTC' , 'Good Until Cancelled'),
	)
	
	ORDER_STATUS = (
	('PENDING' , 'Pending'),
	('COMPLETED', 'Completed'),
	('CANCELLED', 'Cancelled'),
	)

	ORDER_TYPES = (
        ('MARKET' , 'Market'),
        ('LIMIT' , 'Limit') , 
        ('STOP' ,  'Stop' ) ,
        ('STOP_LIMIT' , 'Stop Limit'),
        )

	ORDER_ACTION = (
	('BUY', 'Buy'),
	('SELL', 'Sell'),
	)
# End constants declaration

	portfolio_entry = models.ForeignKey('PortfolioEntry' , null = False) # Each Ticket Entry must be tied to a portfolio entry	
	date_added = models.DateTimeField(db_column ='DateAdded',auto_now_add=True) #Store insertion date of trade
	date_executed = models.DateTimeField(db_column='DateExecuted',null=True,auto_now=True) #Store execution date of trade,included cancelled time

	order_action = models.CharField(max_length = 4, choices = ORDER_ACTION, default = 'BUY' )
	duration = models.CharField(max_length=3, choices = DURATION, default = 'DAY')
	order_type = models.CharField(max_length = 10, choices = ORDER_TYPES , default = 'MARKET' )
	order_status = models.CharField(max_length=9, choices = ORDER_STATUS , default = 'PENDING')
	stop_reached = models.NullBooleanField() # Has the stop price been reached? Will convert to limit then
	limit_price = models.DecimalField(max_digits = 5, decimal_places = 2, db_column ='LimitPrice', null = True,blank=True) #Stores the limit price if the order is limit,can be null if order is market type

	execution_price = models.DecimalField(max_digits = 5, decimal_places = 2, db_column='ExecutionPrice', null=True, blank=True) #Can be zero if cancelled
	stop_price = models.DecimalField(max_digits = 5, decimal_places = 2, db_column ='StopPrice', null = True, blank=True) #Stores Stop price if order is stop
    
class PortfolioEntry (Entry):

	user_name = models.ForeignKey(LeagueUser, blank = False)
        user_league = models.ForeignKey(League, blank=False, related_name = 'UserLeaguePE') #the league the portfolio entry is tied to 
	open = models.BooleanField() # 1 if person is not net zero (still short or long), 0 if they are net zero
	buy_entry = models.ForeignKey(TicketEntry,related_name='buy_ticket', null = True) # Maps to a buy entry,could be null if short
	sell_entry = models.ForeignKey(TicketEntry,related_name='sell_ticket', null = True) # Maps to a sell entry, can be null if long
	#The above 2 will need to become manytomany if we allow a partial amount of shares to be sold (like 100/500) and quantity will need to be moved into TicketEntry
