# source: https://raw.githubusercontent.com/matthieu-hm/freqtrade_consumer_producer_strategies/f2ec1e8fe84e2f37a235f5945cc39418ef9c7086/DummyConsumerStrategy.py
import copy
import logging
import pathlib
import rapidjson
import freqtrade.vendor.qtpylib.indicators as qtpylib
import numpy as np
import talib.abstract as ta
import pandas as pd
import pandas_ta as pta
from freqtrade.strategy.interface import IStrategy
from freqtrade.strategy import merge_informative_pair
from pandas import DataFrame, Series
from functools import reduce, partial
from freqtrade.persistence import Trade, LocalTrade
from datetime import datetime, timedelta
import time
from typing import Optional
import warnings

log = logging.getLogger(__name__)
# log.setLevel(logging.DEBUG)
warnings.simplefilter(action='ignore', category=pd.errors.PerformanceWarning)

class github_matthieu_hm_freqtrade_consumer_producer_strategies__DummyConsumerStrategy__20230401_113618(IStrategy):
    INTERFACE_VERSION: int = 3


    #############################################################
    # Strategy parameters -->

    timeframe = '5m'

    stoploss = -0.05

    # <-- Strategy parameters
    #############################################################


    #############################################################
    # Producers / Consumer

    is_consumer = False

    process_only_new_candles = True


    def __init__(self, config: dict) -> None:
        super().__init__(config)

        if ('external_message_consumer' in self.config and 'producers' in self.config['external_message_consumer']
                and self.config['external_message_consumer']['enabled']
                and len(self.config['external_message_consumer']['producers']) > 0):
            self.is_consumer = True
            self.process_only_new_candles = False  # required for consumers


    def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if self.is_consumer:
            return self.get_dataframe_from_producers(dataframe, metadata['pair'])

        # ... (strategy logic)
        return dataframe


    def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if self.is_consumer:
            # Dataframe already analysed
            return dataframe

        # ... (strategy logic)
        return dataframe


    def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
        if self.is_consumer:
            # Dataframe already analysed
            return dataframe

        # ... (strategy logic)
        return dataframe


    # OPTIONAL: If the strategy uses other callbacks that require the dataframe
    #           check if the dataframe is available before (for the consumer)


    # # OPTIONAL: If the strategy uses this callback
    # def adjust_trade_position(self, trade: Trade, current_time: datetime,
    #                       current_rate: float, current_profit: float,
    #                       min_stake: Optional[float], max_stake: float,
    #                       current_entry_rate: float, current_exit_rate: float,
    #                       current_entry_profit: float, current_exit_profit: float,
    #                       **kwargs) -> Optional[float]:
    #     if (self.position_adjustment_enable == False):
    #         return None

    #     if (self.is_consumer and not self.has_access_to_dataframe_from_producers(trade.pair)):
    #         # Consumer started before the producer that handles this pair and has active trades
    #         # No data available yet, do nothing
    #         return None

    #     # ... (strategy logic)
    #     return None


    # # OPTIONAL: If the strategy uses this callback
    # def custom_exit(self, pair: str, trade: 'Trade', current_time: 'datetime', current_rate: float,
    #                 current_profit: float, **kwargs):
    #     if (self.is_consumer and not self.has_access_to_dataframe_from_producers(pair)):
    #         # Consumer started before the producer that handles this pair and has active trades
    #         # No data available yet, do nothing
    #         return None

    #     # ... (strategy logic)
    #     return None


# +---------------------------------------------------------------------------+
# |                              Consumer                                     |
# +---------------------------------------------------------------------------+

    def get_dataframe_from_producers(self, dataframe: DataFrame, pair: str) -> DataFrame:
        for producer in self.config['external_message_consumer']['producers']:
            if (producer['name']):
                # This func returns the analyzed dataframe, and when it was analyzed
                producer_dataframe, _ = self.dp.get_producer_df(pair, producer_name=producer['name'])

                if not producer_dataframe.empty:
                    log.debug(f"[{pair}] Get dataframe from producer \"{producer['name']}\"")
                    return producer_dataframe

        # No dataframe provided by any producer: minimal dataframe fallback
        required_columns_default_0 = ['enter_long', 'enter_short', 'exit_long', 'exit_short']
        required_columns_default_none = ['enter_tag','exit_tag']

        dataframe[required_columns_default_0] = 0
        dataframe[required_columns_default_none] = None
        log.debug(f"[{pair}] No dataframe found from producers")
        return dataframe


    def has_access_to_dataframe_from_producers(self, pair: str) -> bool:
        for producer in self.config['external_message_consumer']['producers']:
            if (producer['name']):
                # This func returns the analyzed dataframe, and when it was analyzed
                producer_dataframe, _ = self.dp.get_producer_df(pair, producer_name=producer['name'])

                if not producer_dataframe.empty:
                    log.debug(f"[{pair}] Found dataframe: producer \"{producer['name']}\"")
                    return True

        log.debug(f"[{pair}] No dataframe found from producers")
        return False
