# -*- coding: utf-8 -*-
"""

Created on 20180311

@author: Matthew
"""
from .position import Position
import logging
import numpy as np
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)

class Account():

    def __str__(self):
        s = 'class account: you can buy, hold, and dump all stocks in this class'
        return s

    def __init__(self,cash,tradingHabit):
        '''
        tradingHabit: 'OpenPrice'|'ClosePrice'|   OpenPrice is prefered
        '''
        self.initialCash = cash
        self.__cash = cash
        self.positionList = []
        self.__totalValue = cash   #
        self.__positionListValue = 0   #
        self.tradingHabit = tradingHabit
        self.runningDays = 0
    
    def printMe(self):
        logger.warn('     --------- my account status -----------')
        logger.warn('     account--initialCash: %0.2f'%self.initialCash)
        logger.warn('     account--cash: %0.2f'%self.cash)
        logger.warn('     account--positionListValue: %0.2f'%self.positionListValue)
        logger.warn('     account--totalValue: %0.2f'%self.totalValue)
        logger.warn('     account--len of positionList: %d'%len(self.positionList))
        
        #print('account--Name of positionList',[x.SecuCode for x in self.positionList])
        logger.warn('     ---------------------------------------')

    @property
    def cash(self):
        return self.__cash

    @cash.setter
    def cash(self,value):
        if value < -1:
            raise ValueError('cash below -1 is not possible')
        self.__cash = value

    @property
    def totalValue(self):
        return self.__totalValue

    @totalValue.setter
    def totalValue(self,value):
        if value < -1:
            raise ValueError('totalValue below -1 is not possible')
        self.__totalValue = value

    @property
    def positionListValue(self):
        return self.__positionListValue
    
    @positionListValue.setter
    def positionListValue(self,value): 
        if value < -1:
            raise ValueError('positionListValue below -1 is not possible, can be below 0 slightly because of the rounding')
        self.__positionListValue = value

    def isempty(self):
        if len(self.positionList) > 0:
            return False
        else:
            return True

    def buy(self,stock,evenCash):
        '''
        excecute the buy action, evenCash is total cash / stock #
        '''
        #print('buy')
        #print('buy','stock.TradeStatus',stock.TradeStatus,stock.SecuCode)

        price = stock.OpenPrice if self.tradingHabit == 'OpenPrice' else stock.ClosePrice
        boughtAmount = np.floor(evenCash/price/100)*100
        #print('evenCash: %d, price: %0.2f, boughtAmount: %s, boughtValue: %d'%(evenCash,price,boughtAmount,price*boughtAmount))

        #print('boughtAmount:%d'%boughtAmount)
        if boughtAmount <= 0:
            #print('not enough evenCash,evenCash: %d,price %0.2f, boughtAmount:%d'%(evenCash,price,boughtAmount))
            return None
        
        #create Position Object    
        stockPosition = Position(stock,boughtAmount,price)
        
        #print('SecuCode,price,amount,value,',stockPosition.SecuCode,stockPosition.boughtPrice,stockPosition.boughtAmount,stockPosition.positionValue)

        #update positionList
        self.positionList.append(stockPosition)
        #print('self.positionList: ',self.positionList)
        
        self.cash -= price * boughtAmount
        #print('self.cash:',self.cash)

        #updata positionValue
        self.positionListValue += price * boughtAmount
        
        #update totalValue
        self.totalValue = self.positionListValue + self.cash
        #print('totalValue: %d'%self.totalValue)

        #self.runningDays += 1     
         
        
    def countrunningDays(self):
        self.runningDays += 1
    
    def getPositionList(self):
        return self.positionList

    def getnetValue(self):
        return self.getTotalValue()/self.initialCash

    def getTotalValue(self):
        return self.totalValue 
    
    def updatePositionListValue(self):
        #print('updatePositionListValue')
        #print(x.positionValue for x in self.positionList)
        #value = 0
        for x in self.positionList:
            #print(x.SecuCode,x.positionValue)
            if x.positionValue == None: # 君正集团 20130704 没有bar
                x.positionValue = 0
            #value += x.positionValue
        #return value
        return sum(x.positionValue for x in self.positionList)
    
    def getPositionListvalue(self):
        return self.positionListValue

    def sellAvailableForSell(self,NameList):
        '''
        dump all available position
        '''
        self.initialCash = self.cash
        #print('sellAvailableForSell') # print here means execute once in that loop
        for stockName in NameList:
            for position in self.positionList:
                if position.SecuCode == stockName:
                    #print('stockName: %s, position.positionValue: %s, positionListValue: %s, len(positionList): %d'\
                    #%(stockName,position.positionValue,self.positionListValue,len(self.positionList)))

                    self.initialCash += position.positionValue
                    self.cash += position.positionValue
                    self.positionListValue -= position.positionValue
                    self.positionList.remove(position)

        #self.runningDays += 1  
    
    def sell(self,stock):
        '''
        sell individual stock
        '''
        for position in self.positionList:
            if position.SecuCode == stock.SecuCode:
                self.positionList.remove(position) # don't need to empty position object, python will clean the cache after certain while 
        

    def held(self,day,updatedStock):
        '''
        update position's market value in the positionList
        '''
        #logger.warning('held')
        myList = [x.SecuCode for x in updatedStock]
        if not myList:
            return 'no positions to hold 1 '
        #print('myList: ',myList,[x.ClosePrice for x in updatedStock])

        if updatedStock is None:
            print('no position to hold 2')
            return 'No data for %s'%day

        for position in self.positionList:
            for stock in updatedStock:
                if position.SecuCode == stock.SecuCode:
                    #print('match',position.SecuCode,position.SecuCode)
                    position.remainInAccount(stock,2)  # method1 or method2 in position.py

        self.positionListValue = self.updatePositionListValue()
        self.totalValue = self.positionListValue + self.cash

 
            








