import os
from pathlib import Path

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.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, p, t, q, y):
    f = open(filename, 'w')
    f.write("""# File generated by pMuTT (v 1.2.21) on 2020-07-09 16:03:04.988190
# See documentation for OpenMKM YAML file here:
# https://vlachosgroup.github.io/openmkm/input
inlet_gas:
    flow_rate: \"""" + str(q) + """ cm3/s"
phases:
    bulk:
        name: bulk
    gas:
        initial_state: "NH3:1.0"
        name: gas
    surfaces:
    -   initial_state: "RU(T):1.0"
        name: terrace
    -   initial_state: "RU(S):1.0"
        name: step
reactor:
    cat_abyv: "1500 /cm"
    temperature_mode: "isothermal"
    pressure_mode: "isobaric"
    pressure: \"""" + str(p) + """ atm"
    temperature: \"""" + str(t) + """ K"
    type: "cstr"
    volume: "1.0 cm3"
simulation:
    end_time: "100 s"
    init_step: 1.0e-10
    output_format: "csv"
    solver:
        atol: 1.0e-10
        rtol: 1.0e-5
    stepping: "logarithmic"
    transient: false""")
    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(new_species, param_keys, params):
    R = pmutt.constants.R(units='kJ/mol/K')
    if param_keys is not None:
        for i, key in enumerate(param_keys):
            for spec in new_species:
                if spec.name == key:
                    spec.a_high[-2] += params[i] / R
                    spec.a_low[-2] += params[i] / R
    return new_species


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')
    # Create NASA polynomials from the species
    species = [Nasa.from_model(references=refs, **ind_species_data)
               for ind_species_data in species_data]

    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]
