import pandas as pd
import datetime
import numpy as np

import market_trade.core.CoreTraidMath as CoreTraidMath
import market_trade.core.CoreDraw as CoreDraw
from tqdm import tqdm

from market_trade.core.indicators import *


class coreSignalTrande():
    def __init__(self,
                 data=pd.DataFrame(),
                 dataType='candel',
                 mode='online',
                 batchSize=None,
                 indParams=None,
                 signalParams=None,
                 # needFig=False,
                 # showOnlyIndex=False,
                 # drawFig=False,
                 # equalityGap=0
                 ):

        self.data = data.reset_index(drop=True)
        self.onlineData = data.reset_index(drop=True)
        self.dataType = dataType
        self.mode = mode
        self.ans = None
        self.softAnalizList = np.asarray([])
        self.hardAnalizList = np.asarray([])
        self.analizMetrics = {}
        self.indParams = indParams
        self.signalParams = signalParams
        self.batchSize = batchSize
        # self.needFig=needFig
        # self.showOnlyIndex=showOnlyIndex
        # self.drawFig=drawFig
        # self.equalityGap=equalityGap

    # Роутер получения ответа
    def getAns(self, data):
        # ans='Error: unknown Mode!'
        ans = None
        print("Start processing...")
        if self.mode == 'online':
            ans = self.getOnlineAns(data.reset_index(drop=True))
        elif self.mode == 'retro':
            ans = self.getRetroAns(data)
        elif self.mode == 'retroFast':
            ans = self.getRetroFastAns(data)
        print("Processing DONE!")
        return ans

    # Ретро режим, где расширяется окно добавлением новых элементов
    def getRetroAns(self, data):
        ans = np.asarray([])
        for i in tqdm(range(self.batchSize, len(data) - 1)):
            # self.onlineData=self.data[0:i]
            window_data = data[0:i]
            window_data.reset_index(drop=True)
            ans = np.append(ans, (self.getOnlineAns(window_data)))
        self.ans = ans
        self.getAnaliz()
        self.getMetrix()
        return ans

    # Ретро режим, где двигается окно
    def getRetroFastAns(self, data):
        # print('d - ',data)
        ans = np.asarray([])
        for i in tqdm(range(len(data) - 1 - self.batchSize)):
            # self.onlineData=self.data[i:i+self.batchSize]
            window_data = data[i:i + self.batchSize]
            # print('win - ',window_data)
            window_data.reset_index(drop=True)
            # print('win - ',window_data)
            ans = np.append(ans, (self.getOnlineAns(window_data)))
        self.ans = ans
        self.getAnaliz()
        self.getMetrix()
        return ans

    # Метод, который будет переопределять каждый дочерний класс
    def getOnlineAns(self):
        return 'Error'

    def getAnaliz(self):
        print("Start analiz...")
        for i in (range(len(self.ans))):
            sourceValue = self.data[self.signalParams['source']][i + self.batchSize]
            targetValue = self.data[self.signalParams['target']][i + self.batchSize + 1]
            if (targetValue) > sourceValue:
                if self.ans[i] == 1:
                    self.softAnalizList = np.append(self.softAnalizList, 1)
                    self.hardAnalizList = np.append(self.hardAnalizList, 1)
                elif self.ans[i] == -1:
                    self.softAnalizList = np.append(self.softAnalizList, -1)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)
                else:
                    self.softAnalizList = np.append(self.softAnalizList, 0)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)

            elif (targetValue) < sourceValue:
                if self.ans[i] == 1:
                    self.softAnalizList = np.append(self.softAnalizList, -1)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)
                elif self.ans[i] == -1:
                    self.softAnalizList = np.append(self.softAnalizList, 1)
                    self.hardAnalizList = np.append(self.hardAnalizList, 1)
                else:
                    self.softAnalizList = np.append(self.softAnalizList, 0)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)
            else:
                if self.ans[i] == 1:
                    self.softAnalizList = np.append(self.softAnalizList, -1)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)
                elif self.ans[i] == -1:
                    self.softAnalizList = np.append(self.softAnalizList, -1)
                    self.hardAnalizList = np.append(self.hardAnalizList, -1)
                else:
                    self.softAnalizList = np.append(self.softAnalizList, 0)
                    self.hardAnalizList = np.append(self.hardAnalizList, 1)
        print("Analiz DONE!")
        return 0

    def getMeteixDict(self, d):
        '''
        1 - (сбывшиеся + несбывшиеся) \ (сбывшиеся + несбывшиеся +0)
        2 - (сбывшиеся - несбывшиеся) \ (сбывшиеся + несбывшиеся +0)
        '''
        return {

            '1': (d['1'] + d['-1']) / (d['1'] + d['-1'] + d['0']),
            '2': (d['1'] - d['-1']) / (d['1'] + d['-1'] + d['0']),

        }

    def getMetrix(self):

        softAnalizCount = {'-1': 0, '0': 0, '1': 0}
        hardAnalizCount = {'-1': 0, '0': 0, '1': 0}
        for i in range(len(self.softAnalizList)):
            softAnalizCount[str(int(self.softAnalizList[i]))] += 1
            hardAnalizCount[str(int(self.hardAnalizList[i]))] += 1
        self.analizMetrics = {'softAnaliz': self.getMeteixDict(softAnalizCount),
                              'hardAnaliz': self.getMeteixDict(hardAnalizCount)
                              }


class signal_BB(coreSignalTrande):

    def __init__(self,
                 data=pd.DataFrame(),
                 dataType='candel',
                 mode='online',
                 batchSize=None,
                 indParams=None,
                 signalParams=None,
                 ):
        super().__init__(
            data=data,
            dataType=dataType,
            mode=mode,
            batchSize=batchSize,
            indParams=indParams,
            signalParams=signalParams,
        )

        if self.indParams == None:
            indParams = {'MeanType': 'SMA', 'window': 15, 'valueType': 'low', 'kDev': 2}
        else:
            indParams = self.indParams
        self.BB = ind_BB(
            data=data,
            options=indParams,
        )

    def getOnlineAns(self, data):
        ans = 0
        # print(data)

        self.BB.getAns(data)
        # print(BB)
        lastValue = data[self.signalParams['source']].to_list()[-1]
        if lastValue > self.BB.ans['pSTD'][-1]:
            ans = -1
        elif lastValue < self.BB.ans['mSTD'][-1]:
            ans = +1
        else:
            ans = 0

        return ans
