###############################################################################
# __   _            _____    _____
# | \ | |          / ____|  / ____|
# |  \| |  _   _  | |      | (___
# | . ` | | | | | | |       \___ \
# | |\  | | |_| | | |____   ____) |
# |_| \_|  \__,_|  \_____| |_____/
#
# Fast constraint solving in Python  - https://github.com/yangeorget/nucs
#
# Copyright 2024-2026 - Yan Georget
###############################################################################
from numba import njit  # type: ignore
from numpy.typing import NDArray

from nucs.constants import EVENT_MASK_MIN_MAX, MAX, MIN, PROP_CONSISTENCY, PROP_INCONSISTENCY


def get_complexity_sum_eq(n: int, parameters: NDArray) -> float:
    """
    Returns the time complexity of the propagator as a float.
    :param n: the number of variables
    :param parameters: the parameters, unused here
    :return: a float
    """
    return n


@njit(cache=True)
def get_triggers_sum_eq(n: int, variable: int, parameters: NDArray) -> int:
    """
    This propagator is triggered whenever there is a change in the domain of a variable.
    :param parameters: the parameters, unused here
    :return: an array of triggers
    """
    return EVENT_MASK_MIN_MAX


@njit(cache=True)
def compute_domains_sum_eq(domains: NDArray, parameters: NDArray) -> int:
    """
    Implements Sigma_i x_i = x_{n-1}.
    :param domains: the domains of the variables, x is an alias for domains
    :param parameters: the parameters of the propagator, unused here
    :return: the status of the propagation (consistency, inconsistency or entailment) as an int
    """
    n = len(domains) - 1
    domain_sum_min = -domains[-1, MIN] + domains[:n, MAX].sum()
    domain_sum_max = -domains[-1, MAX] + domains[:n, MIN].sum()
    for i in range(n):
        new_min = domains[i, MAX] - domain_sum_min
        new_max = domains[i, MIN] - domain_sum_max
        if new_min > domains[i, MIN]:
            domains[i, MIN] = new_min
        if new_max < domains[i, MAX]:
            domains[i, MAX] = new_max
        if domains[i, MIN] > domains[i, MAX]:
            return PROP_INCONSISTENCY
    new_min = domains[-1, MAX] + domain_sum_max
    new_max = domains[-1, MIN] + domain_sum_min
    if new_min > domains[-1, MIN]:
        domains[-1, MIN] = new_min
    if new_max < domains[-1, MAX]:
        domains[-1, MAX] = new_max
    if domains[-1, MIN] > domains[-1, MAX]:
        return PROP_INCONSISTENCY
    return PROP_CONSISTENCY
