# Copyright 2021 Vincent Texier <vit@free.fr>
#
# This software is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
from typing import Any, Dict, List, Optional

from tikka.domains.entities.account import Account
from tikka.domains.entities.universal_dividend import UniversalDividend
from tikka.interfaces.adapters.network.indexer.universal_dividends import (
    IndexerUniversalDividendsInterface,
)
from tikka.interfaces.adapters.repository.universal_dividends import (
    UniversalDividendsRepositoryInterface,
)


class UniversalDividends:
    """
    UniversalDividends domain class
    """

    def __init__(
        self,
        repository: UniversalDividendsRepositoryInterface,
        indexer_universal_dividends: IndexerUniversalDividendsInterface,
    ):
        """
        Init Transfers domain

        :param repository: TransfersRepositoryInterface adapter instance
        :param indexer_universal_dividends: IndexerUniversalDividendsInterface adapter instance
        """
        self.repository = repository
        self.indexer_universal_dividends = indexer_universal_dividends

    def add(self, universal_dividend: UniversalDividend):
        """
        Add universal_dividend to repository

        :param universal_dividend: UniversalDividend instance
        :return:
        """
        self.repository.add(universal_dividend)

    def delete_by_address(self, address: str) -> None:
        """
        Delete Universal Dividend history for address

        :param address: Account address of history to delete
        :return:
        """
        self.repository.delete_by_address(address)

    def delete_all(self) -> None:
        """
        Delete all Universal Dividends in repository

        :return:
        """
        self.repository.delete_all()

    def count(self, address: str) -> int:
        """
        Return number of Universal Dividend for address in repository

        :return:
        """
        return self.repository.count(address)

    def list(
        self,
        address: str,
        filters: Optional[Dict[str, Any]] = None,
        sort_column: str = UniversalDividendsRepositoryInterface.COLUMN_TIMESTAMP,
        sort_order: str = UniversalDividendsRepositoryInterface.SORT_ORDER_DESCENDING,
        limit: int = 100,
        offset: int = 0,
    ) -> List[UniversalDividend]:
        """
        List Universal Dividend for address,
        from repository with optional filters and sort_column

        :param address: Account address
        :param filters: Dict with {column: value} filters or None
        :param sort_column: Sort column constant, UniversalDividendsRepositoryInterface.COLUMN_TIMESTAMP by default
        :param sort_order: Sort order constant, UniversalDividendsRepositoryInterface.SORT_ORDER_DESCENDING by default
        :param limit: Number of rows to return
        :param offset: Offset of first row to return
        :return:
        """
        return self.repository.list(
            address, filters, sort_column, sort_order, limit, offset
        )

    def network_fetch_history_for_account(self, account: Account, limit: int) -> None:
        """
        Fetch history of last Universal Dividends for account

        :param account: Account instance to filter
        :param limit: Maximum number of Universal Dividends to fetch
        :return:
        """
        universal_dividends = self.indexer_universal_dividends.list(
            account.address, limit=limit
        )
        self.repository.set_history(account.address, universal_dividends)

    def network_fetch_total_count_for_address(self, address: str) -> int:
        """
        Fetch total count of Universal Dividends from and to address

        :param address: Address to filter
        :return:
        """
        return self.indexer_universal_dividends.count(address)
