"""The sample makes Renko bars requests with volume via Expression request 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"
BRICK_SIZE = 5
BRICK_UNIT = "Tick"  # "Price" is another possible value

# 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


def CreateSubExpression(outputName):
    return f"RBop({SYMBOL},{BRICK_SIZE},{BRICK_UNIT}, 0, 1):{outputName}"


class RenkoVolumeViaExpressionRequest(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.CreateExpressionRequest())
        # It is possible to add only required sub-expressions
        request.AddSubExpression(CreateSubExpression("curve1"), "RenkoHigh")
        request.AddSubExpression(CreateSubExpression("curve2"), "RenkoLow")
        request.AddSubExpression(CreateSubExpression("boolean"), "RenkoUp")
        request.AddSubExpression(CreateSubExpression("High"), "High")
        request.AddSubExpression(CreateSubExpression("Low"), "Low")
        request.AddSubExpression(CreateSubExpression("Volume"), "Volume")
        request.RangeStart = 0
        request.RangeEnd = -10
        request.SubscriptionLevel = win32com.client.constants.tslEachTick
        request.UpdatesEnabled = True
        request.SessionsFilter = "all"

        LOG.info("Request expression")
        self.renkoWithVolumeExpression = self.celEnvironment.cqgCEL.RequestExpression(request)

        LOG.info("Waiting for 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 OnExpressionResolved(self, cqgExpression, cqgError):
        if cqgError is not None:
            error = win32com.client.Dispatch(cqgError)
            LOG.error("OnExpressionResolved: Code: %d Description: %s", error.Code, error.Description)
            self.eventDone.set()
        else:
            self._traceOutputs(cqgExpression, "-", "OnExpressionResolved")

    def OnExpressionAdded(self, cqgExpression):
        self._traceOutputs(cqgExpression, "-", "OnExpressionAdded")

    def OnExpressionInserted(self, cqgExpression, index):
        self._traceOutputs(cqgExpression, index, "OnExpressionInserted")

    def OnExpressionUpdated(self, cqgExpression, index):
        self._traceOutputs(cqgExpression, index, "OnExpressionUpdated")

    def OnExpressionRemoved(self, cqgExpression, index):
        self._traceOutputs(cqgExpression, index, "OnExpressionRemoved")

    def _traceOutputs(self, cqgExpression, index, methodName):
        expression = win32com.client.Dispatch(cqgExpression)
        LOG.info("%s: Expressions count: %d index %d", methodName, expression.Count, index)
        for outputs in expression:
            LOG.info(
                "  Timestamp %s RenkoHigh %f RenkoLow %f RenkoUp %f High %f Low %f Volume %d",
                outputs.Timestamp,
                outputs(0),
                outputs(1),
                outputs(2),
                outputs(3),
                outputs(4),
                outputs(5)
            )


if __name__ == "__main__":
    CELEnvironment.Start(RenkoVolumeViaExpressionRequest)
