"""Assumption input and calculations for individual policies.
This Space is a child Space of :mod:`~simplelife.model.Projection`,
and it holds assumption parameters and rates used
by the :mod:`~simplelife.model.Projection` Space.
.. blockdiag::
   blockdiag {
     default_node_color="#D5E8D4";
     default_linecolor="#628E47";
     node_width=150;
     Proj[label="Projection\\n[PolicyID, ScenID=1]", stacked];
     Proj <- Assumptions [hstyle=composition];
     Proj <- Policy [hstyle=composition];
   }
.. rubric:: Parameters
Since :mod:`~simplelife.model.Projection` is parameterized with
:attr:`PolicyID` and :attr:`ScenID`, this Space is also
parameterized as a child space of :mod:`~simplelife.model.Projection`.
For example, ``simplelife.Projection[1].Assumptions.ExpsMaintSA()``
represents the expense maintenance per sum assured for Policy 1.
Attributes:
    PolicyID(:obj:`int`): Policy ID
    ScenID(:obj:`int`, optional): Scenario ID, defaults to 1.
.. rubric:: References
Attributes:
    AssumptionTables: `ExcelRange`_ object holding data read from the
        Excel range *AssumptionTable* in *input.xlsx*.
    MortalityTable: `ExcelRange`_ object holding mortality tables.
        The data is read from *MortalityTables* range in *input.xlsx*.
    prod: Alias for :func:`simplelife.Projection.Policy.Product`
    polt: Alias for :func:`simplelife.Projection.Policy.PolicyType`
    gen: Alias for :func:`simplelife.Projection.Policy.Gen`
    sex: Alias for :func:`simplelife.Projection.Policy.Sex`
    AsmpLookup: Alias for :func:`simplelife.Input.AsmpLookup`
.. _ExcelRange:
   https://docs.modelx.io/en/latest/reference/dataclient.html#excelrange
"""
from modelx.serialize.jsonvalues import *
_formula = None
_bases = []
_allow_none = None
_spaces = []
# ---------------------------------------------------------------------------
# Cells
[docs]def BaseMortRate(x):
    """Bae mortality rate"""
    table_id = AsmpLookup.match("BaseMort", prod(), polt(), gen()).value
    return MortalityTables[table_id, sex(), x] 
[docs]def CnsmpTax():
    """Consumption tax rate"""
    return AsmpLookup("CnsmpTax") 
[docs]def CommInitPrem():
    """Initial commission per premium"""
    result = AsmpLookup.match("CommInitPrem", prod(), polt(), gen()).value
    if result is not None:
        return result
    else:
        raise ValueError('CommInitPrem not found') 
[docs]def CommRenPrem():
    """Renewal commission per premium"""
    result = AsmpLookup.match("CommRenPrem", prod(), polt(), gen()).value
    if result is not None:
        return  result
    else:
        raise ValueError('CommRenPrem not found') 
[docs]def CommRenTerm():
    """Renewal commission term"""
    result = AsmpLookup.match("CommRenTerm", prod(), polt(), gen()).value
    if result is not None:
        return result
    else:
        raise ValueError('CommRenTerm not found') 
[docs]def ExpsAcqAnnPrem():
    """Acquisition expense per annualized premium"""
    return AsmpLookup.match("ExpsAcqAnnPrem", prod(), polt(), gen()).value 
[docs]def ExpsAcqPol():
    """Acquisition expense per policy"""
    return AsmpLookup.match("ExpsAcqPol", prod(), polt(), gen()).value 
[docs]def ExpsAcqSA():
    """Acquisition expense per sum assured"""
    return AsmpLookup.match("ExpsAcqSA", prod(), polt(), gen()).value 
[docs]def ExpsMaintAnnPrem():
    """Maintenance expense per annualized premium"""
    return AsmpLookup.match("ExpsMaintPrem", prod(), polt(), gen()).value 
[docs]def ExpsMaintPol():
    """Maintenance expense per policy"""
    return AsmpLookup.match("ExpsMaintPol", prod(), polt(), gen()).value 
[docs]def ExpsMaintSA():
    """Maintenance expense per sum assured"""
    return AsmpLookup.match("ExpsMaintSA", prod(), polt(), gen()).value 
[docs]def InflRate():
    """Inflation rate"""
    return AsmpLookup("InflRate") 
[docs]def LastAge():
    """Age at which mortality becomes 1"""
    x = 0
    while True:
        if BaseMortRate(x) == 1:
            return x
        x += 1 
[docs]def MortFactor(y):
    """Mortality factor"""
    table = AsmpLookup.match("MortFactor", prod(), polt(), gen()).value
    if table is None:
        raise ValueError('MortFactor not found')
    result = AssumptionTables.get((table, y), None)
    if result is None:
        return MortFactor(y-1)
    else:
        return result 
[docs]def MortTable():
    """Mortality Table"""
    result = AsmpLookup.match("BaseMort", prod(), polt(), gen()).value
    if result is not None:
        return MortalityTables(result).MortalityTable
    else:
        raise ValueError('MortTable not found') 
[docs]def SurrRate(y):
    """Surrender Rate"""
    table = AsmpLookup.match("Surrender", prod(), polt(), gen()).value
    if table is None:
        raise ValueError('Surrender not found')
    result =  AssumptionTables.get((table, y), None)
    if result is None:
        return SurrRate(y-1)
    else:
        return result 
# ---------------------------------------------------------------------------
# References
AsmpLookup = ("Interface", ("...", "Input", "AsmpLookup"), "auto")
AssumptionTables = ("Pickle", 2325077011464)
MortalityTables = ("Pickle", 2325070426248)
gen = ("Interface", ("..", "Policy", "Gen"), "auto")
polt = ("Interface", ("..", "Policy", "PolicyType"), "auto")
prod = ("Interface", ("..", "Policy", "Product"), "auto")
sex = ("Interface", ("..", "Policy", "Sex"), "auto")