"""The sample demonstrates how to work with a simultaneous historical requests limit.
The limit affects only unresolved historical requests.
A historical request is not affected by the limit as soon as it is resolved even if the request includes updates.
"""

import logging
import sys
import threading
import time

import win32com.client

import CELEnvironment

assert sys.version_info >= (3, 6), "The python version should be 3.6 or later"

#region Settings

# Replace it with enabled symbol or symbols
SYMBOLS = ["EDA?" + str(series) for series in range(1, 21)]
# The simultaneous historical requests limit value (it is limited by CQG API)
SIMULTANEOUS_HISTORICAL_REQUESTS_COUNT = 10

# 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 SimultaneousHistoricalRequestsSample(CELEnvironment.CELSinkBase):
    def __init__(self):
        self.requestsPool = threading.BoundedSemaphore(SIMULTANEOUS_HISTORICAL_REQUESTS_COUNT)

    def Init(self, celEnvironment):
        self.celEnvironment = celEnvironment

    def CreateRequest(self, symbol):
        request = win32com.client.Dispatch(self.celEnvironment.cqgCEL.CreateTimedBarsRequest())
        request.Symbol = symbol
        request.RangeStart = 0
        request.RangeEnd = -10
        request.HistoricalPeriod = win32com.client.constants.hpDaily
        request.UpdatesEnabled = True
        request.SessionsFilter = "all"
        return request

    def Start(self):
        for sym in SYMBOLS:
            request = self.CreateRequest(sym)
            self.requestsPool.acquire()  # pylint: disable=consider-using-with
            self.celEnvironment.cqgCEL.RequestTimedBars(request)
            LOG.info("A request for %s is placed", sym)

        LOG.info(
            "All %d requests have been placed. Waiting for 10 seconds to make sure that"
            " updates are available for all placed requests.",
            len(SYMBOLS)
        )

        time.sleep(10)

        LOG.info("Done!")

    def OnTimedBarsResolved(self, cqgTimedBars, cqgError):
        bars = win32com.client.Dispatch(cqgTimedBars)
        if cqgError is not None:
            error = win32com.client.Dispatch(cqgError)
            LOG.error("OnTimedBarsResolved failed: Error code: %d Description: %s", error.Code, error.Description)
        else:
            LOG.info("OnTimedBarsResolved (%s)", bars.Request.Symbol)
        self.requestsPool.release()

    def OnTimedBarsUpdated(self, cqgTimedBars, index):
        bars = win32com.client.Dispatch(cqgTimedBars)
        LOG.info("OnTimedBarsUpdated (%s): Updated bar index: %d", bars.Request.Symbol, index)


if __name__ == "__main__":
    CELEnvironment.Start(SimultaneousHistoricalRequestsSample)
