import numpy as np
from math import sqrt
from .utils import priority_vector


# noinspection PyCallingNonCallable
def consistency_index(matrix):
    nrow = matrix.shape[0]
    eigenvals, eigenvectors = np.linalg.eig(matrix)
    eigen_real_part = np.real(eigenvals)
    max_eigen = eigen_real_part[0]
    ci = (max_eigen - nrow) / (nrow - 1)
    return ci


def consistency_ratio(matrix, source="lin2015"):
    nrow = matrix.shape[0]
    if source == "R_FuzzyAHP":
        random_index = (0, 0, 0.52, 0.89, 1.11, 1.25, 1.35, 1.40, 1.45, 1.49, 1.52, 1.54, 1.56, 1.58, 1.59,)
    else:
        random_index = (0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41, 1.46, 1.49, 1.52, 1.54, 1.56, 1.58, 1.59,)

    ci = consistency_index(matrix)
    if nrow > len(random_index):
        raise (
            ValueError,
            f"Cannot calculate Consistency Ratio for matrices with more then {len(random_index)}",
        )

    cr = ci / random_index[nrow - 1]
    return cr


def euclidean_distance(empirical, theoretical):
    nrows, ncols = empirical.shape
    weighted_elements_sum = 0
    for i in range(nrows):
        for j in range(ncols):
            weighted_elements_sum += (empirical[i, j] - theoretical[i, j]) ** 2

    distance = sqrt(weighted_elements_sum)
    return distance


def minimum_violation(matrix):
    pv = priority_vector(matrix)
    nrows, ncols = matrix.shape
    mv = 0
    for i in range(nrows):
        for j in range(ncols):
            if pv[i] > pv[j] and matrix[j, i] > 1:
                error = 1
            elif pv[i] == pv[j] and matrix[j, i] != 1:
                error = 0.5
            elif pv[i] != pv[j] and matrix[j, i] == 1:
                error = 0.5
            else:
                error = 0
            mv += error
    return mv
