#
# Doyle-Fuller-Newman (DFN) Model
#
import pybamm
from .base_lithium_ion_model import BaseModel


class DFN(BaseModel):
    """
    Doyle-Fuller-Newman (DFN) model of a lithium-ion battery, from
    :footcite:t:`Marquis2019`. See :class:`pybamm.lithium_ion.BaseModel` for more
    details.

    Examples
    --------
    >>> model = pybamm.lithium_ion.DFN()
    >>> model.name
    'Doyle-Fuller-Newman model'

    """

    def __init__(self, options=None, name="Doyle-Fuller-Newman model", build=True):
        # For degradation models we use the full form since this is a full-order model
        self.x_average = False
        super().__init__(options, name)

        self.set_submodels(build)

        pybamm.citations.register("Doyle1993")

    def set_intercalation_kinetics_submodel(self):
        for domain in ["negative", "positive"]:
            electrode_type = self.options.electrode_types[domain]
            if electrode_type == "porous":
                intercalation_kinetics = self.get_intercalation_kinetics(domain)
                phases = self.options.phases[domain]
                for phase in phases:
                    submod = intercalation_kinetics(
                        self.param, domain, "lithium-ion main", self.options, phase
                    )
                    self.submodels[f"{domain} {phase} interface"] = submod

                if len(phases) > 1:
                    self.submodels[f"total {domain} interface"] = (
                        pybamm.kinetics.TotalMainKinetics(
                            self.param, domain, "lithium-ion main", self.options
                        )
                    )

    def set_particle_submodel(self):
        for domain in ["negative", "positive"]:
            if self.options.electrode_types[domain] == "planar":
                continue
            particle = getattr(self.options, domain)["particle"]
            for phase in self.options.phases[domain]:
                if particle == "Fickian diffusion":
                    submod = pybamm.particle.FickianDiffusion(
                        self.param, domain, self.options, phase=phase, x_average=False
                    )
                elif particle in [
                    "uniform profile",
                    "quadratic profile",
                    "quartic profile",
                ]:
                    submod = pybamm.particle.PolynomialProfile(
                        self.param, domain, self.options, phase=phase
                    )
                elif particle == "MSMR":
                    submod = pybamm.particle.MSMRDiffusion(
                        self.param, domain, self.options, phase=phase, x_average=False
                    )
                    # also set the submodel for calculating stoichiometry from
                    # potential
                    self.submodels[f"{domain} {phase} stoichiometry"] = (
                        pybamm.particle.MSMRStoichiometryVariables(
                            self.param,
                            domain,
                            self.options,
                            phase=phase,
                            x_average=False,
                        )
                    )
                self.submodels[f"{domain} {phase} particle"] = submod
                self.submodels[f"{domain} {phase} total particle concentration"] = (
                    pybamm.particle.TotalConcentration(
                        self.param, domain, self.options, phase
                    )
                )

    def set_solid_submodel(self):
        for domain in ["negative", "positive"]:
            if self.options.electrode_types[domain] == "planar":
                continue
            if self.options["surface form"] == "false":
                submodel = pybamm.electrode.ohm.Full
            else:
                submodel = pybamm.electrode.ohm.SurfaceForm
            self.submodels[f"{domain} electrode potential"] = submodel(
                self.param, domain, self.options
            )

    def set_electrolyte_concentration_submodel(self):
        self.submodels["electrolyte diffusion"] = pybamm.electrolyte_diffusion.Full(
            self.param, self.options
        )

    def set_electrolyte_potential_submodel(self):
        surf_form = pybamm.electrolyte_conductivity.surface_potential_form

        if self.options["electrolyte conductivity"] not in ["default", "full"]:
            raise pybamm.OptionError(
                "electrolyte conductivity '{}' not suitable for DFN".format(
                    self.options["electrolyte conductivity"]
                )
            )

        if self.options["surface form"] == "false":
            self.submodels["electrolyte conductivity"] = (
                pybamm.electrolyte_conductivity.Full(self.param, self.options)
            )

        if self.options["surface form"] == "false":
            surf_model = surf_form.Explicit
        elif self.options["surface form"] == "differential":
            surf_model = surf_form.FullDifferential
        elif self.options["surface form"] == "algebraic":
            surf_model = surf_form.FullAlgebraic

        for domain in ["negative", "separator", "positive"]:
            if self.options.electrode_types.get(domain) == "planar":
                continue
            self.submodels[f"{domain} surface potential difference"] = surf_model(
                self.param, domain, self.options
            )

    def set_summary_variables(self):
        self.set_default_summary_variables()
