from __future__ import annotations

import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import minimize

from plot_utils import finish_figure, matlab_figure, set_color_order, style_axes
from subaxis import subaxis


h = 0.0
delta = 0.02


def E(x):
    # error function
    global h, delta
    ynn = 2 / (np.pi - 2)
    n = len(x)
    g = np.zeros(n + 1)
    for i in range(1, n):
        if i < n - 1:
            dxR = (x[i + 1] - x[i]) / h
        else:
            dxR = (1 - x[i]) / h
        dxL = (x[i] - x[i - 1]) / h
        y = delta + h * i
        g[i] = np.sqrt((1 + 0.5 * dxR**2 + 0.5 * dxL**2) / y)
    dx1 = (x[1] - x[0]) / h
    g[0] = 0.5 * np.sqrt((1 + dx1**2) / delta)
    dxn = (1 - x[n - 1]) / h
    g[n] = 0.5 * np.sqrt((1 + dxn**2) / ynn)
    s = 0.0
    for i in range(n + 1):
        s = s + g[i]
    dx0 = x[0] / delta
    g0 = 2 * np.sqrt(delta * (1 + dx0**2))
    s = g0 + h * s
    return float(s)


def fig9_22():
    global h, delta

    delta = 0.02

    # number of internal grid points
    n = 8

    # starting guess for fminsearch routine
    ynn = 2 / (np.pi - 2)
    y = np.linspace(delta, ynn, n + 1)
    h = y[1] - y[0]
    xi = np.zeros(n)
    for iy in range(n):
        xi[iy] = y[iy] / ynn

    result = minimize(
        E,
        xi,
        method="Nelder-Mead",
        options={"maxfev": 1_000_000, "maxiter": 1_000_000, "xatol": 1e-6},
    )
    sol = result.x
    fval = result.fun
    exitflag = int(result.success)
    output = {
        "message": result.message,
        "iterations": result.nit,
        "function_evaluations": result.nfev,
        "success": result.success,
    }
    x = np.concatenate(([0], sol, [1]))
    y = np.concatenate(([0], y))

    print("fval =", fval)
    print("exitflag =", exitflag)
    print("output =", output)

    fig1 = matlab_figure(1, 658, 230)
    ax1 = subaxis(1, 1, 1, 1, "MT", -0.01, "MB", 0.2, "MR", -0.01, "ML", 0.03, "P", 0.04)
    set_color_order(ax1)

    ax1.plot(x, y, "or", markersize=8, linewidth=2)
    # exact solution
    th = np.linspace(0, 0.5 * np.pi, 100)
    xe = np.zeros(100)
    ye = np.zeros(100)
    for it in range(100):
        xe[it] = ynn * (th[it] - np.sin(th[it]))
        ye[it] = ynn * (1 - np.cos(th[it]))
    ax1.plot(xe, ye, "b", linewidth=1.6)
    ax1.grid(True)
    ax1.axis([0, 1, 0, 2])
    ax1.set_xlabel("x-axis")
    ax1.set_ylabel("y-axis")
    style_axes(ax1, 14)

    # exportgraphics(gcf,'/Users/mark/Desktop/brac.eps')
    finish_figure(fig1, "brac.png")

    # this figure is not in text
    fig2 = matlab_figure(2, 658, 230)
    ax2 = fig2.add_subplot(111)
    set_color_order(ax2)

    ax2.plot(x, y, "or", markersize=8, linewidth=2)
    th = np.linspace(0, 0.5 * np.pi, 100)
    for it in range(100):
        xe[it] = ynn * (th[it] - np.sin(th[it]))
        ye[it] = ynn * (1 - np.cos(th[it]))
    ax2.plot(xe, ye, "b", linewidth=1.6)
    ax2.grid(True)
    ax2.axis([0, 0.1, 0, 0.2])
    ax2.set_xlabel("x-axis")
    ax2.set_ylabel("y-axis")
    style_axes(ax2, 14)
    fig2.tight_layout()
    finish_figure(fig2, "brac_zoom.png")
    plt.show()


if __name__ == "__main__":
    fig9_22()
