import os
from pathlib import Path

import numpy as np
import pandas as pd
import pmutt.constants
from pmutt import pmutt_list_to_dict
from pmutt.empirical.nasa import Nasa
from pmutt.empirical.references import Reference, References
from pmutt.empirical.shomate import Shomate
from pmutt.io.excel import read_excel
from pmutt.io.omkm import organize_phases, write_cti
from pmutt.mixture.cov import PiecewiseCovEffect
from pmutt.omkm.reaction import BEP, SurfaceReaction
from pmutt.omkm.units import Units


def edit_reactor_yaml(filename, y, T):
    f = open(filename, 'w')
    f.write("""# File generated by pMuTT (v 1.2.21) on 2022-02-22 18:54:31.620473
# See documentation for OpenMKM YAML file here:
# https://vlachosgroup.github.io/openmkm/input
inlet_gas:
    flow_rate: "2.0 cm3/s"
phases:
    gas:
        initial_state: "ClCH2CH2Cl:""" + str(y[0]) + """, H2:""" + str(y[1]) + """, Ar:""" + str(y[2]) + """"
        name: gas
    surfaces:
    -   initial_state: "PtCu111(*):1.0"
        name: PtCu111
reactor:
    cat_abyv: "463 /cm"
    temperature_mode: "isothermal"
    pressure: "1.5 atm"
    temperature: """ + str(T) + """
    type: "cstr"
    volume: "2. cm3"
simulation:
    end_time: "250 s"
    init_step: 1.0e-10
    output_format: "csv"
    solver:
        atol: 1.0e-12
    stepping: "logarithmic"
    """)
    f.close()


def edit_thermo_xml(cti_path,
                    thermo_data,
                    P,
                    T,
                    **kwargs):
    use_motz_wise = kwargs['use_motz_wise']
    [reactions, species, phases, units, interactions] = thermo_data
    write_cti(reactions=reactions, species=species, phases=phases, units=units,
              lateral_interactions=interactions, filename=cti_path,
              T=T, P=P,  # in atm
              use_motz_wise=use_motz_wise)


def update_param_thermo(reactions, units, T, P, **kwargs):

    A_units = '{}/{}2'.format(units.quantity, units.length)
    rxn_no = kwargs['perturb'][0]
    perturb = kwargs['perturb'][1]
    if reactions[rxn_no].is_adsorption:
        reactions[rxn_no].sticking_coeff *= perturb
    else:
        reactions[rxn_no].A = reactions[rxn_no].get_A(T=T, P=P, include_entropy=False,
                                                      units=A_units) * perturb
    return reactions


def load_thermo_objects(input_path_str):
    try:
        file_path = os.path.dirname(__file__)
    except NameError:
        file_path = Path().resolve()

    os.chdir(file_path)
    input_path = str(Path(input_path_str).resolve())

    # First, we will designate the units to write the CTI and YAML file.
    units_data = read_excel(io=input_path, sheet_name='units')[0]
    units = Units(**units_data)

    # Second, we will open the input spreadsheet and read the `refs` sheet.
    try:
        refs_data = read_excel(io=input_path, sheet_name='refs')
    except:
        # If references are not used, skip this section
        refs = None
    else:
        refs = [Reference(**ref_data) for ref_data in refs_data]
        refs = References(references=refs)

    # Read the species' data
    species_data = read_excel(io=input_path, sheet_name='species')
    species = [Shomate(name=spec['name'],
                       T_low=spec['T_low'],
                       T_high=spec['T_high'],
                       a=np.zeros(8),
                       elements=spec['elements'],
                       phase=spec['phase'],
                       n_sites=spec['n_sites'] if 'n_sites' in spec.keys() else None)
               for spec in species_data]

    species_shomate = pd.read_excel(io=Path('../inputs/12DCA_ThermoData.xlsx').resolve(),
                                    sheet_name='Sheet1', index_col='Species')

    for spec in species:
        if spec.name in species_shomate.index:
            spec.a = species_shomate.loc[spec.name].to_numpy()[:8]

    try:
        beps_data = read_excel(io=input_path, sheet_name='beps')
    except:
        beps = None
        species_with_beps = species.copy()
    else:
        beps = [BEP(**bep_data) for bep_data in beps_data]
        species_with_beps = species + beps

    # Read reactions
    # Convert species to dictionary for easier reaction assignment
    species_with_beps_dict = pmutt_list_to_dict(species_with_beps)

    reactions_data = read_excel(io=input_path, sheet_name='reactions')
    reactions = [SurfaceReaction.from_string(species=species_with_beps_dict, **reaction_data) \
                 for reaction_data in reactions_data]
    # Read lateral interactions (optional)
    try:
        interactions_data = read_excel(io=input_path,
                                       sheet_name='lateral_interactions')
    except:
        # If no lateral interactions exist, skip this section
        interactions = None
    else:
        interactions = [PiecewiseCovEffect(**interaction_data) \
                        for interaction_data in interactions_data]

    # Reading Phases
    # Read data from Excel sheet about phases
    phases_data = read_excel(io=input_path, sheet_name='phases')
    phases = organize_phases(phases_data, species=species, reactions=reactions,
                             interactions=interactions)

    return [reactions, species, phases, units, interactions]
