import random
from ssa import DataInput, f

#Фун-я генерирующая иксы, которые x1<x2<x3
def genRandX():
    try:
        x1 = random.randint(-10, 3)
        x3 = random.randint(-3, 10)
        if x1 != x3:
            x2 = random.randint(x1, x3)
            step1(x1, x2, x3)
        else:
            genRandX()
    except:
        genRandX()


# фун-я Принимающая данные на вход алгоритма.
def dataEntry(data):
    data = data.split()    # Делим строку по пробелу
    if len(data) == 2:     # Если пользователь передал 2 параметра, то объявляем формулу и пытаемся определить эпсилон
        global formula, E
        formula = data[0]
        try:
            E = float(data[1])
        except:
            # Если эпсилон будет не числом, то пернём ошибку
            return "Ошибка! Проверьте правильность эпсилона."

        # Передаём формулу методу поиска отрезка и получаем словарь с ответом, наличием ошибки и листом со всеми иксами
        decision = DataInput(formula)

        # Если ошибка == True, то алгоритм поиска отрезка не справился, возвращаем пользователю текст ошибки
        if decision['error']:
            return decision['answer']
        else:
            # Иначе мы присваиваем иксы (причём наоборот)
            x1 = decision['all_x'][-3]
            x2 = decision['all_x'][-2]
            x3 = decision['all_x'][-1]
            # Возываем шаг первый и передаем ему иксы
            step1(x1, x2, x3)
            return response


def step1(accX1, accX2, accX3, accRes=""):
    global response
    # это счётчик для проверки попыток сгенерировать иксы
    count = 0

    # Если удовлетворяется условие X1<X2<x3
    if accX1 < accX2 and accX2 < accX3:
        fx1 = f(accX1)
        fx2 = f(accX2)
        fx3 = f(accX3)

        # Если удовлетворяется условие f(x1)>f(x2)<f(x3)
        if fx1 > fx2 and fx3 > fx2:
            n = 0           # Счётчик иттераций

            # Эта переменная содержит временный строку с ответом, которая на каждом шаге будет дополняться
            res = accRes + f"1.1\nx₁={accX1}\nx₂={accX2}\nx₃={accX3}\nf(x₁)={fx1}\nf(x₂)={fx2}\nf(x₃)={fx3}\n"
            # Переходим ко 2 шагу, передаём иксы, f от иксов, счетчик, и строку с ответом
            step2(accX1, accX2, accX3, fx1, fx2, fx3, n, res)
        else:
            # генерируем новый набор иксов
            if count > 4:
                response = "Не удалось найти подходящие X, попробуйте снова"
            else:
                count += 1
                genRandX()
    else:
        if count > 4:
            response = "Не удалось найти подходящие X, попробуйте снова"
        else:
            count+=1
            genRandX()


def step2(accX1, accX2, accX3, accFx1, accFx2, accFx3, accN, accRes):
    # пробуем вычислить y (через try т.к. возможно деление на ноль)
    try:
        y = 0.5 * (((accX2**2 - accX3**2)*accFx1 + (accX3**2 - accX1**2)*accFx2 + (accX1**2 - accX2**2)*accFx3)/((accX2 - accX3)*accFx1 + (accX3 - accX1)*accFx2 + (accX1 - accX2)*accFx3))
        # прибавляем счётчик т.к. этот шаг может иттерироваться несколько раз
        n = accN + 1
        res = accRes + f"{n}.2\ny={y}\n"
        step3(accX1, accX2, accX3, accFx1, accFx2, accFx3, y, n, res)
    except Exception as e:
        global response
        response = f"Ошибка в вычислении y"
        print(formula, accX1, accX2, accX3, e)

def step3(accX1, accX2, accX3, accFx1, accFx2, accFx3, accY, accN, accRes):
    global response
    # Вычисляем f(y)
    fy = f(accY)
    # Если f(y) меньше эпсилона, то выдаем ответ, который подхватит первая фун-я и выдаст return`ом
    if abs(accY - accX2) <= E:
        response = accRes + f"{accN}.3\nОтвет: x={accY}, f(x)={fy}"
    else:
        # Это гавнокод (как и все выше,но за это мне ппц стыдно)
        # Я не знаю как это реализовать по-другому, поэтому здесть тупо в лоб сравниваются иксы и ищется такая тройка, которая
        # x1<x2<x3 И f(x1)>f(x2)<f(x3)
        res = accRes + f"Выбираем тройку иксов из: {accX1, accX2, accX3, accY}\n"
        if accX1 < accX2 < accY and accFx1 > accFx2 < fy:
            step1(accX1, accX2, accY, res)
        elif accX1 < accX3 < accY and accFx1 > accFx3 < fy:
            step1(accX1, accX3, accY, res)
        elif accX2 < accX3 < accY and accFx2 > accFx3 < fy:
            step1(accX2, accX3, accY, res)
        elif accX2 < accX1 < accY and accFx2 > accFx1 < fy:
            step1(accX2, accX1, accY, res)
        elif accX1 < accY < accX2 and accFx1 > fy < accFx2:
            step1(accX1, accY, accX2, res)
        elif accX1 < accY < accX3 and accFx1 > fy < accFx3:
            step1(accX1, accY, accX3, res)
        elif accX2 < accY < accX3 and accFx2 > fy < accFx3:
            step1(accX2, accY, accX3, res)
        elif accX2 < accY < accX1 and accFx2 > fy < accFx1:
            step1(accX2, accY, accX1, res)
        elif accY < accX1 < accX2 and fy > accFx1 < accFx2:
            step1(accY, accX1, accX2, res)
        elif accY < accX1 < accX3 and fy > accFx1 < accFx3:
            step1(accY, accX1, accX3, res)
        elif accY < accX2 < accX1 and fy > accFx2 < accFx1:
            step1(accY, accX2, accX1, res)
        elif accY < accX2 < accX3 and fy > accFx2 < accFx3:
            step1(accY, accX2, accX3, res)
        elif accX3 < accX1 < accY and accFx3 > accFx1 < fy:
            step1(accX3, accX1, accY, res)
        elif accX3 < accX2 < accY and accFx3 > accFx2 < fy:
            step1(accX3, accX2, accY, res)
        elif accX3 < accY < accX1 and accFx3 > fy < accFx1:
            step1(accX3, accY, accX1, res)
        elif accY < accX1 < accX2 and fy > accFx1 < accFx2:
            step1(accY, accX1, accX2, res)
        elif accY < accX3 < accX1 and fy > accFx3 < accFx1:
            step1(accY, accX3, accX1, res)
        elif accY < accX3 < accX2 and fy > accFx3 < accFx2:
            step1(accY, accX3, accX2, res)
        else:
            response = "Не удалось выбрать X-ы"



if __name__ == "__main__":
    print(dataEntry("2*x**2-12*x 0.01"))