"""Abrahamson and Silva (1996, :cite:`abrahamson96`) duration model."""
from __future__ import division

import numpy as np

from . import model

__author__ = "Albert Kottke"


class AbrahamsonSilva1996(model.Model):
    """Abrahamson and Silva (1996, :cite:`abrahamson96`) duration model.

    Parameters
    ----------
    scenario : :class:`pygmm.model.Scenario`
        earthquake scenario

    """

    NAME = "Abrahamson Silva (1996)"
    ABBREV = "AS96"

    PARAMS = [
        model.NumericParameter("mag", True, 4, 7.5),
        model.NumericParameter("dist_rup", True, 0, 250),
        # FIXME add site_cond to Scenario
        model.CategoricalParameter("site_cond", True, ["soil", "rock"]),
    ]

    def __init__(self, scenario):
        super(AbrahamsonSilva1996, self).__init__(scenario)

        s = self._scenario

        stress_drop = np.exp(5.204 + 0.851 * (s.mag - 6))
        moment = 10 ** (1.5 * s.mag + 16.05)

        self._ln_dur = np.log(
            (stress_drop / moment) ** (-1 / 3) / (4.9e6 * 3.2)
            + 0.805 * (1 if s.site_cond == "soil" else 0)
            + 0.063 * max(s.dist_rup - 10, 0)
        ) + self.calc_ln_dur_incr(0.75)
        self._std_err = 0.55

    @property
    def duration(self):
        return np.exp(self._ln_dur)

    @property
    def std_err(self):
        return self._std_err

    @staticmethod
    def calc_ln_dur_incr(nias):
        # Mask out inappropriate values
        nias = np.asarray(nias)
        mask = (nias < 0.10) | (0.95 < nias)
        nias[mask] = np.nan

        # Compute the increment due to the difference in the normalized Arias
        # intensity
        ln_i_ratio = np.log((nias - 0.05) / (1 - nias))
        ln_dur_incr = -0.532 + 0.552 * ln_i_ratio - 0.0262 * ln_i_ratio**2

        return ln_dur_incr

    def interp(self, nias, stds=None):
        # Mask out inappropriate values
        nias = np.asarray(nias)
        mask = (nias < 0.10) | (0.95 < nias)
        nias[mask] = np.nan

        ln_dur = self._ln_dur + self.calc_ln_dur_incr(nias)

        if stds is not None:
            std_errs = np.interp(
                nias,
                [
                    0.10,
                    0.15,
                    0.20,
                    0.25,
                    0.30,
                    0.35,
                    0.40,
                    0.45,
                    0.50,
                    0.55,
                    0.60,
                    0.65,
                    0.70,
                    0.75,
                    0.80,
                    0.85,
                    0.90,
                    0.95,
                ],
                [
                    0.843,
                    0.759,
                    0.713,
                    0.691,
                    0.674,
                    0.660,
                    0.646,
                    0.636,
                    0.628,
                    0.616,
                    0.605,
                    0.594,
                    0.582,
                    0.565,
                    0.545,
                    0.528,
                    0.510,
                    0.493,
                ],
            )
            ln_dur = ln_dur + np.array(stds)[:, np.newaxis] * std_errs

        return np.exp(ln_dur)
