import datetime

from tqz_extern.pandas_operator import pandas
from op_futures.op_objects.bar_data import BarData
from op_futures.op_objects.tick_data import TickData

class BarGenerate:

    def __init__(self, csv_path: str):
        self.__ticks_df = pandas.read_csv(csv_path)
        self.__ticks = []


        self.__bar_df = pandas.DataFrame(
            columns=['date_time', 'open_price', 'high_price', 'low_price', 'close_price', 'volume', 'open_interest']
        )
        self.__bars = []


    @staticmethod
    def timestamp_to_datetime(timestamp) -> str:
        ret_dt = datetime.datetime.fromtimestamp(timestamp / 1000)
        ret_dt = ret_dt - datetime.timedelta(hours=8)

        return f'{ret_dt.date()} {ret_dt.time()}'


    def make_bar_dataframe(self, interval_secs: int):
        first_timestamp = self.__ticks_df.iloc[0]['Timestamp']
        last_timestamp = self.__ticks_df.iloc[-1]['Timestamp']

        interval = interval_secs * 1000  # 1 min
        while True:
            next_start_timestamp = first_timestamp + interval
            if first_timestamp > last_timestamp:
                # print('bar_df: ' + str(self.bar_df))
                break

            cur_snap_df = self.__ticks_df[(self.__ticks_df['Timestamp'] >= first_timestamp) & (self.__ticks_df['Timestamp'] < next_start_timestamp)]
            if len(cur_snap_df) > 0:
                new_row = {
                    'date_time': self.timestamp_to_datetime(timestamp=next_start_timestamp),
                    'open_price': cur_snap_df.iloc[0]['LastPrice'],
                    'high_price': cur_snap_df['LastPrice'].max(),
                    'low_price': cur_snap_df['LastPrice'].min(),
                    'close_price': cur_snap_df.iloc[-1]['LastPrice'],
                    'volume': str(cur_snap_df.iloc[-1]['Volume'] - cur_snap_df.iloc[0]['Volume']),
                    'open_interest': str(cur_snap_df.iloc[-1]['OpenInterest'] - cur_snap_df.iloc[0]['OpenInterest'])
                }

                self.__bar_df.loc[len(self.__bar_df)] = new_row

            first_timestamp = next_start_timestamp

        self.__bar_df['interval_secs'] = interval_secs
        self.__bar_df['price_tick'] = self.__ticks_df['PriceTick'].unique()[0]
        self.__bar_df['volume_multiple'] = self.__ticks_df['VolumeMultiple'].unique()[0]
        return self

    def bars_df_value(self):
        return self.__bar_df

    def bars_list_value(self) -> [BarData]:
        if 0 == len(self.__bars):
            [self.__bars.append(BarData(
                date_time=str(row['date_time']),
                open_price=float(row['open_price']), high_price=float(row['high_price']), low_price=float(row['low_price']), close_price=float(row['close_price']),
                volume=float(row['volume']), open_interest=float(row['open_interest']),
                interval_secs=float(row['interval_secs']),
                price_tick=float(row['price_tick']), volume_multiple=float(row['volume_multiple'])
            )) for index, row in self.__bar_df.iterrows()]

        return self.__bars

    def ticks_df_value(self):
        return self.__ticks_df

    def ticks_list_value(self) -> [TickData]:
        if 0 == len(self.__ticks):
            [self.__ticks.append(TickData(
                time_stamp=row['Timestamp'],
                update_time=row['UpdateTime'],
                update_millisec=row['UpdateMillisec'],
                instrument_id=row['InstrumentID'],
                exchange_instrument=row['ExchangeInstrument'],
                open_price=row['OpenPrice'],
                hightest_price=row['HighestPrice'],
                lowest_price=row['LowestPrice'],
                last_price=row['LastPrice'],
                volume=row['Volume'],
                turnover=row['Turnover'],
                open_interest=row['OpenInterest'],
                upper_limit_price=row['UpperLimitPrice'],
                lower_limit_price=row['LowerLimitPrice'],
                pre_close_price=row['PreClosePrice'],
                pre_open_interest=row['PreOpenInterest'],
                price_tick=row['PriceTick'],
                volume_multiple=row['VolumeMultiple'],
                action_day=row['ActionDay'],
                ask_price1=row['AskPrice1'], ask_price2=row['AskPrice2'], ask_price3=row['AskPrice3'], ask_price4=row['AskPrice4'], ask_price5=row['AskPrice5'],
                bid_price1=row['BidPrice1'], bid_price2=row['BidPrice2'], bid_price3=row['BidPrice3'], bid_price4=row['BidPrice4'], bid_price5=row['BidPrice5'],
                ask_size1=row['AskSize1'], ask_size2=row['AskSize2'], ask_size3=row['AskSize3'], ask_size4=row['AskSize4'], ask_size5=row['AskSize5'],
                bid_size1=row['BidSize1'], bid_size2=row['BidSize2'], bid_size3=row['BidSize3'], bid_size4=row['BidSize4'], bid_size5=row['BidSize5']
            )) for index, row in self.__ticks_df.iterrows()]

        return self.__ticks


if __name__ == '__main__':
    # bar_df = BarGenerate(csv_path='../op_machine_learning/rb2401.csv').make_bar_dataframe(interval_secs=60).bars_df_value()
    # bars_list = BarGenerate(csv_path='../op_machine_learning/rb2401.csv').make_bar_dataframe(interval_secs=60).bars_list_value()
    ticks_list = BarGenerate(csv_path='../op_machine_learning/rb2401.csv').ticks_list_value()
    print('ticks_list: ' + str(ticks_list))