import os
import numpy as np
import pandas as pd
import openpyxl


def get_cmd(xk, fit):
    plot_flag = 0
#    xk = fit.recover_parameters(xk0, set_member = False)
    return f"python CV_nnp.py NW {fit.infile} {fit.datafile} {xk[0]} {xk[1]} {xk[2]} {xk[3]} {xk[4]} {plot_flag}"

def read_data(infile, filetype = ''):
    print(f"Read data from [{infile}]")

    if not os.path.isfile(infile):
        return None, None, None

    df = pd.read_excel(infile, header = None)
    v00 = df.iloc[0,0]
    if type(v00) != str or v00 == '':
        labels = df.iloc[1, 1:].tolist()
        data = df.iloc[2:, 1:].values
    else:
        labels = df.iloc[0, 0:].tolist()
        data = df.iloc[1:, 0:].values

    data_df = pd.DataFrame(data, columns = labels)
    labels = data_df.columns.tolist()
    data_list = data_df.values.tolist()
    ndata = data_df.shape[0]
    
    if filetype == 'calc':
        V_list   = [data_list[i][0] for i in range(ndata)]
        C_list   = [data_list[i][8] for i in range(ndata)]
    else:
        V_list   = [data_list[i][0] for i in range(ndata)]
        C_list   = [data_list[i][1] for i in range(ndata)]

    nskip = max(1, int(ndata / 25))
    print("ndata=", ndata, nskip)
    print(f"{labels[0]:>10} {labels[1]:>10}")
    for i in range(0, ndata, nskip):
        print(f"{V_list[i]:10.4g} {C_list[i]:10.4g}")

        return labels, [V_list], [C_list]

def save_data(path, labels, data_list):
    df = pd.DataFrame(np.array(data_list).T, columns = labels)
    df.to_excel(path, index = False, header = True) 

def ycal_list(xd_list, xk, fit = None):
    cmd = get_cmd(xk, fit)
#    print(f"launch [{cmd}]")
    os.system(cmd)
    
    labels, x_list, y_list = read_data(fit.datafile, 'calc')
    return [y_list[0]]

def add_history_csv(historyfile, varnames, xk, fmin):
    if not os.path.isfile(historyfile):
        print(f"Create [{historyfile}]")
        with open(historyfile, 'w') as out:
            out.write(f"-iter,min:fmin")
            for i in range(len(xk)):
                out.write(f",{varnames[i]}")
            out.write("\n")

    if os.path.isfile(historyfile):
        print(f"Add fmin and xk to [{historyfile}]")
        iter = -1
        with open(historyfile, 'r') as fp:
            for l in fp:
                iter += 1
        with open(historyfile, 'a') as out:
            out.write(f"{iter},{fmin}")
            for x in xk:
                out.write(f",{x}")
            out.write("\n")

def add_history_xlsx(historyfile, varnames, xk, fmin):
    if not os.path.isfile(historyfile):
        wb = openpyxl.Workbook()
    else:
        wb = openpyxl.load_workbook(historyfile)

    ws = wb.active
    max_row = ws.max_row
    max_col = ws.max_column
    print("max_row=", max_row)

    if max_row <= 1 and ws.cell(row=1, column=1).value is None:
        ws.cell(row=1, column=1, value='-iter')
        ws.cell(row=1, column=2, value='min:fmin')
        for i in range(len(xk)):
            ws.cell(row=1, column=3+i, value=varnames[i])

    ws.cell(row=max_row+1, column=1, value=max_row)
    ws.cell(row=max_row+1, column=2, value=fmin)
    for i in range(len(xk)):
        ws.cell(row=max_row+1, column=3+i, value=xk[i]) 
    wb.save(historyfile)

def add_history(historyfile, varnames, xk, fmin):
    ext = os.path.splitext(historyfile)[1]
    if ext.lower() == ".csv":
        return add_history_csv(historyfile, varnames, xk, fmin)
    elif ext.lower() == ".xlsx":
        return add_history_xlsx(historyfile, varnames, xk, fmin)
    else:
        print(f"Warning: Unsupported extension [{ext}] for history file")
        return

def minimize_func(xk, x_list, y_list, w_list, fit):
    if x_list is None:
        x_list = fit.x_list
    if y_list is None:
        y_list = fit.y_list

#    print("xk=", xk)
    nx = len(x_list[0])
    fmin = 0.0
    xkr = fit.recover_parameters(xk, set_member = False)
    yc_list = ycal_list(x_list, xkr, fit)
    for i in range(nx):
        d  = y_list[0][i] - yc_list[0][i]
        fmin += d * d

    print(f"fmin={fmin:12.4g}")
    
    add_history(fit.historyfile, fit.varname, xkr, fmin)

    return fmin
