# -*- coding: utf-8 -*-

"""
Модуль для вычисления обратных котировок.
"""

__author__ = "Zasimov Alexey"
__email__ = "zasimov-a@yandex-team.ru"

from stocks3.core.stock import Quote
from stocks3.core.quotesconfig import QuotesConfig
from stocks3.core.config import Configurable


def calc_reverse(quote, prices, reverse_quote):
    """
    Вычисляет обратную котировку для котировки quote.

    @param quote: Котировка, для которой вычисляем обратную котировку.
    @param prices: Данные для котировки quote (словарь регион->котировки).
    @param reverse_quote: Обратная котировка.
    """
    assert isinstance(quote, Quote) and isinstance(reverse_quote, Quote)
    assert type(prices) == dict
    reverse = {}
    for region, data in prices.items():
        reverse_data = []
        reverse[region] = reverse_data
        for price in data:
            reverse_price = price.calcReversePrice(reverse_quote)
            reverse_data.append(reverse_price)
    return reverse


class WithReverse(Configurable):
    """
    С конфигурацией обратных котировок.
    """
    def __init__(self, tree, node, quotes_config):
        assert isinstance(quotes_config, QuotesConfig),\
            "Expected QuotesMapper, received %s" % quotes_config.__class__.__name__
        self._quotes_config = quotes_config
        self.reverse_quotes = {}
        Configurable.__init__(self, tree, node)

    def makeConfig(self):
        Configurable.makeConfig(self)
        for quote_node in self.node.findall("reverse-quotes/quote"):
            quote_name = quote_node.attrib["name"]
            quote = self._quotes_config.getQuoteByName(quote_name)
            reverse_quote_name = quote_node.attrib["reverse"]
            reverse_quote = self._quotes_config.getQuoteByName(reverse_quote_name)
            self.reverse_quotes[quote.quote_id] = reverse_quote

    def is_reverse(self, quote):
        assert isinstance(quote, Quote), "Expected Quote for is_reverse, received %s" % quote.__class__.__name__
        return quote.quote_id in map(lambda q: q.quote_id, self.reverse_quotes.values())

    def has_reverse(self, quote):
        return quote.quote_id in self.reverse_quotes

    def get_reverse_quote(self, quote):
        assert isinstance(quote, Quote), "Expected Quote for is_reverse, received %s" % quote.__class__.__name__
        return self.reverse_quotes[quote.quote_id]

    def calc_reverse(self, quote, prices):
        """
        Вычисляем обратные котировки.
        """
        if self.has_reverse(quote):
            reverse_quote = self.get_reverse_quote(quote)
            reverse = calc_reverse(quote, prices, reverse_quote)
            return reverse_quote, reverse
        #  FIXME: не очень хорошо, что здесь возвращается None, а не tuple
        return None

