# -*- coding: utf-8 -*-
"""
Сохраняем данные в базе данных.
"""
from stocks3.core.withdbconfig import WithDBConfiguration
from stocks3.core.saver import Saver
from stocks3.core.factories import savers
from stocks3.share.reversequote import WithReverse
from stocks3.share.db import Database

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


def eq(a, b, eps=0.0000001):
    return abs(a - b) <= eps


class DBSaver(WithDBConfiguration, Saver):
    def __init__(self, tree, node, source):
        self._prices = []
        self.reverse = None
        WithDBConfiguration.__init__(self, tree, node)
        Saver.__init__(self, tree, node, source)
        self.db = Database(self.get_dbinfo())

    def makeConfig(self):
        WithDBConfiguration.makeConfig(self)
        Saver.makeConfig(self)
        self.reverse = WithReverse(self.tree, self.node, self.source.default.quotes_config)

    def save(self, price):
        """
        Сохраняем котировку в списке self._prices.
        """
        self._prices.append(price)

    def _iter_prices(self):
        # Добавляем обратные котировки.
        for price in self._prices:
            yield price
            if self.reverse.has_reverse(price.quote):
                reverse_quote = self.reverse.get_reverse_quote(price.quote)
                reverse = price.calcReversePrice(reverse_quote)
                yield reverse

    def check_if_need_save(self, saved_price, price):
        if saved_price is None:
            return True
        if 'source' in saved_price and saved_price['source'] < self.source.weight:
            return True
        if price.unconfirmed is False and saved_price.get('unconfirmed', False) is True:
            return True
        if eq(saved_price['value'], price.buy.value):
            if 'sell_value' not in saved_price or eq(saved_price['sell_value'], price.sell.value):
                return False
        return True

    def flush(self):
        Saver.flush(self)
        try:
            for price in self._iter_prices():
                saved_price = self.db.select(self.source, price)
                if self.check_if_need_save(saved_price, price):
                    result = self.db.insert_or_update(self.source, price)
                    if result[1]:
                        self._info("update: %s: %s" % (self.source.sourceId, price.show()))
                    else:
                        self._info("insert: %s: %s" % (self.source.sourceId, price.show()))
                else:
                    self._info("skipped: %s: %s" % (self.source.sourceId, price.show()))
                continue

        finally:
            pass

    def clean(self):
        self._prices = []


savers.register("stocks3.savers.DB", DBSaver)
