"""The sample makes Timed Bar request and waits for response and updates 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 BarsRequestSample(CELEnvironment.CELSinkBase):
    def __init__(self):
        self.eventDone = threading.Event()

    def Init(self, celEnvironment):
        self.celEnvironment = celEnvironment

    def Start(self):
        LOG.info("Create timed bars request")
        request = win32com.client.Dispatch(self.celEnvironment.cqgCEL.CreateTimedBarsRequest())
        request.Symbol = SYMBOL
        request.RangeStart = 0
        request.RangeEnd = -10
        request.HistoricalPeriod = win32com.client.constants.hpDaily
        request.DailyBarCloseEx = "LSX"  # Last Quote or Settlement or Exchange close
        request.UpdatesEnabled = True
        request.IncludeOutput(win32com.client.constants.tbrContractVolume, True)
        request.IncludeOutput(win32com.client.constants.tbrCommodityVolume, True)
        request.SessionsFilter = "all"

        LOG.info("Starting the request...")
        self.celEnvironment.cqgCEL.RequestTimedBars(request)

        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 OnTimedBarsResolved(self, cqgTimedBars, cqgError):
        if cqgError is not None:
            error = win32com.client.Dispatch(cqgError)
            LOG.error("OnTimedBarsResolved: Code: %d Description: %s", error.Code, error.Description)
            self.eventDone.set()
        else:
            bars = win32com.client.Dispatch(cqgTimedBars)
            LOG.info("OnTimedBarsResolved: Bars count: %d Bars:", bars.Count)
            for i in range(0, bars.Count):
                self.dumpBar(win32com.client.Dispatch(bars.Item(i)), i)

    def OnTimedBarsAdded(self, cqgTimedBars):
        bars = win32com.client.Dispatch(cqgTimedBars)
        LOG.info("OnTimedBarsAdded: Bars count: %d Bars:", bars.Count)
        for i in range(0, bars.Count):
            self.dumpBar(win32com.client.Dispatch(bars.Item(i)), i)

    def OnTimedBarsUpdated(self, cqgTimedBars, index):
        LOG.info("OnTimedBarsUpdated: Updated bar index %d", index)
        bars = win32com.client.Dispatch(cqgTimedBars)
        self.dumpBar(win32com.client.Dispatch(bars.Item(index)), index)

    def OnTimedBarsRemoved(self, cqgTimedBars, index):
        bars = win32com.client.Dispatch(cqgTimedBars)
        LOG.info("OnTimedBarsRemoved: Bars count: %d : Removed bar index %d", bars.Count, index)
        for i in range(0, bars.Count):
            self.dumpBar(win32com.client.Dispatch(bars.Item(i)), i)

    def dumpBar(self, bar, index):
        LOG.info(
            "   Bar index: %d Timestamp %s Open %f High %f Low %f Close %f ActualVolumeFractional %s "
            "CommodityVolumeFractional %s ContractVolumeFractional %s TickVolume %d",
            index,
            bar.Timestamp,
            bar.Open,
            bar.High,
            bar.Low,
            bar.Close,
            bar.ActualVolumeFractional,
            bar.CommodityVolumeFractional,
            bar.ContractVolumeFractional,
            bar.TickVolume
        )


if __name__ == "__main__":
    CELEnvironment.Start(BarsRequestSample)
