"""The sample makes Renko bars requests and waits for responses for 20 sec"""

import logging
import threading

import win32com.client

import CELEnvironment

#region Settings

# Replace it with enabled symbol
SYMBOL = "DD"

# Logging settings: specify log level and log format here.
# Set log level to DEBUG to see more internal messages.
# See more information about logging lib usage: https://docs.python.org/3/howto/logging-cookbook.html
CELEnvironment.LOG_LEVEL = logging.INFO
# CELEnvironment.LOG_FORMAT = ...

# CELEnvironment.SinkInternal uses own LOG_LEVEL (which is inherited from the global one) and own LOG_FORMAT.
# You can redefine them as follows:
# CELEnvironment.SinkInternal.LOG_LEVEL = logging.DEBUG
# CELEnvironment.SinkInternal.LOG_FORMAT = ...

LOG = CELEnvironment.GetLogger()

#endregion


class RenkoBarsSample(CELEnvironment.CELSinkBase):
    def __init__(self):
        self.eventDone = threading.Event()

    def Init(self, celEnvironment):
        self.celEnvironment = celEnvironment

    def Start(self):
        LOG.info("Create renko bars request")
        request = win32com.client.Dispatch(self.celEnvironment.cqgCEL.CreateRenkoBarsRequest())
        request.Symbol = SYMBOL
        request.RangeStart = 0
        request.RangeEnd = -3
        request.BrickUnit = win32com.client.constants.buTick
        request.BrickSize = 3
        request.Continuation = win32com.client.constants.tsctStandard
        request.SubscriptionLevel = win32com.client.constants.tslEachTick
        request.UpdatesEnabled = True
        request.SessionsFilter = "all"

        LOG.info("Request renko bars")
        self.renkoBars = self.celEnvironment.cqgCEL.RequestRenkoBars(request)

        LOG.info("Waiting results for 20 seconds...")
        self.eventDone.wait(20)

        LOG.info("Done!")

    def OnDataError(self, cqgError, errorDescription):
        if cqgError is not None:
            error = win32com.client.Dispatch(cqgError)
            LOG.error("OnDataError: Code: %d Description: %s", error.Code, error.Description)
        self.eventDone.set()

    def OnRenkoBarsResolved(self, cqgRenkoBars, cqgError):
        if cqgError is not None:
            error = win32com.client.Dispatch(cqgError)
            LOG.error("OnRenkoBarsResolved: Code: %d Description: %s", error.Code, error.Description)
            self.eventDone.set()
        else:
            self._traceBars(cqgRenkoBars, "-", "OnRenkoBarsResolved")

    def OnRenkoBarsAdded(self, cqgRenkoBars):
        self._traceBars(cqgRenkoBars, "-", "OnRenkoBarsAdded")

    def OnRenkoBarsInserted(self, cqgRenkoBars, index):
        self._traceBars(cqgRenkoBars, index, "OnRenkoBarsInserted")

    def OnRenkoBarsUpdated(self, cqgRenkoBars, index):
        self._traceBars(cqgRenkoBars, index, "OnRenkoBarsUpdated")

    def OnRenkoBarsRemoved(self, cqgRenkoBars, index):
        self._traceBars(cqgRenkoBars, index, "OnRenkoBarsRemoved")

    def _traceBars(self, cqgRenkoBars, index, methodName):
        renkoBars = win32com.client.Dispatch(cqgRenkoBars)
        LOG.info("%s: Bars count: %d index %s",methodName, renkoBars.Count, index)
        for renkoBar in renkoBars:
            LOG.info(
                "  Bar: Timestamp %s RenkoHigh %f RenkoLow %f RenkoUp %f Open %f High %f Low %f Close %f "
                "TickVolume %d VolumeFractional %s",
                renkoBar.Timestamp,
                renkoBar.RenkoHigh,
                renkoBar.RenkoLow,
                renkoBar.RenkoUp,
                renkoBar.Open,
                renkoBar.High,
                renkoBar.Low,
                renkoBar.Close,
                renkoBar.TickVolume,
                renkoBar.ActualVolumeFractional
            )


if __name__ == "__main__":
    CELEnvironment.Start(RenkoBarsSample)
