from fielddisplay import fielddisplay
from checkfield import checkfield
from WriteData import WriteData


class fourierlove(object):
    """
    Fourier Love Number class definition

       Usage:
          fourierlove = fourierlove()
    """
    def __init__(self):  # {{{
        self.nfreq = 0
        self.frequencies = 0
        self.sh_nmax = 0
        self.sh_nmin = 0
        self.g0 = 0
        self.r0 = 0
        self.mu0 = 0
        self.allow_layer_deletion = 0
        self.love_kernels = 0
        self.forcing_type = 0

    #set defaults
        self.setdefaultparameters()
    #}}}

    def __repr__(self):  # {{{
        string = '   Fourier Love class:'
        string = "%s\n%s" % (string, fielddisplay(self, 'nfreq', 'number of frequencies sampled (default 1, elastic) [Hz]'))
        string = "%s\n%s" % (string, fielddisplay(self, 'frequencies', 'frequencies sampled (convention defaults to 0 for the elastic case) [Hz]'))
        string = "%s\n%s" % (string, fielddisplay(self, 'sh_nmax', 'maximum spherical harmonic degree (default 256, .35 deg, or 40 km at equator)'))
        string = "%s\n%s" % (string, fielddisplay(self, 'sh_nmin', 'minimum spherical harmonic degree (default 1)'))
        string = "%s\n%s" % (string, fielddisplay(self, 'g0', 'adimensioning constant for gravity (default 10) [m / s^2]'))
        string = "%s\n%s" % (string, fielddisplay(self, 'r0', 'adimensioning constant for radius (default 6378e3) [m]'))
        string = "%s\n%s" % (string, fielddisplay(self, 'mu0', 'adimensioning constant for stress (default 1.0e11) [Pa]'))
        string = "%s\n%s" % (string, fielddisplay(self, 'allow_layer_deletion', 'allow for migration of the integration boundary with increasing spherical harmonics degree (default 1)'))
        string = "%s\n%s" % (string, fielddisplay(self, 'love_kernels', 'compute love numbers at depth? (default 0)'))
        string = "%s\n%s" % (string, fielddisplay(self, 'forcing_type', 'integer indicating the nature and depth of the forcing for the Love number calculation (default 11) :'))
        string = "%s\n%s" % (string, '                                                     1:  Inner core boundary -- Volumic Potential')
        string = "%s\n%s" % (string, '                                                     2:  Inner core boundary --  Pressure')
        string = "%s\n%s" % (string, '                                                     3:  Inner core boundary --  Loading')
        string = "%s\n%s" % (string, '                                                     4:  Inner core boundary --  Tangential traction')
        string = "%s\n%s" % (string, '                                                     5:  Core mantle boundary --  Volumic Potential')
        string = "%s\n%s" % (string, '                                                     6:  Core mantle boundary --  Pressure')
        string = "%s\n%s" % (string, '                                                     7:  Core mantle boundary --  Loading')
        string = "%s\n%s" % (string, '                                                     8:  Core mantle boundary --  Tangential traction')
        string = "%s\n%s" % (string, '                                                     9:  Surface--  Volumic Potential')
        string = "%s\n%s" % (string, '                                                     10: Surface--  Pressure')
        string = "%s\n%s" % (string, '                                                     11: Surface--  Loading')
        string = "%s\n%s" % (string, '                                                     12: Surface--  Tangential traction ')

        return string
    #}}}

    def extrude(self, md):  # {{{
        return self
    #}}}

    def setdefaultparameters(self):  # {{{
        #we setup an elastic love number computation by default.
        self.nfreq = 1
        self.frequencies = [0]  #Hz
        self.sh_nmax = 256  # .35 degree, 40 km at the equator.
        self.sh_nmin = 1
        self.g0 = 9.81 # m/s^2
        self.r0 = 6371e3 #m
        self.mu0 = 1e11 # Pa
        self.allow_layer_deletion = 1
        self.love_kernels = 0
        self.forcing_type = 11

        return self
    #}}}

    def checkconsistency(self, md, solution, analyses):  # {{{
        md = checkfield(md, 'fieldname', 'love.nfreq', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.frequencies', 'NaN', 1, 'Inf', 1, 'numel', [md.love.nfreq])
        md = checkfield(md, 'fieldname', 'love.sh_nmax', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.sh_nmin', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.g0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.r0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.mu0', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0)
        md = checkfield(md, 'fieldname', 'love.allow_layer_deletion', 'values', [0, 1])
        md = checkfield(md, 'fieldname', 'love.love_kernels', 'values', [0, 1])
        md = checkfield(md, 'fieldname', 'love.forcing_type', 'NaN', 1, 'Inf', 1, 'numel', [1], '>', 0, '<=', 12)
        if md.love.sh_nmin <= 1 and md.love.forcing_type == 9:
            raise RuntimeError("Degree 1 not supported for Volumetric Potential forcing. Use sh_min >= 2 for this kind of calculation.")

        return md
    # }}}

    def marshall(self, prefix, md, fid):  # {{{
        WriteData(fid, prefix, 'object', self, 'fieldname', 'nfreq', 'format', 'Integer')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'frequencies', 'format', 'DoubleMat', 'mattype', 3)
        WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmax', 'format', 'Integer')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'sh_nmin', 'format', 'Integer')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'g0', 'format', 'Double')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'r0', 'format', 'Double')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'mu0', 'format', 'Double')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'allow_layer_deletion', 'format', 'Boolean')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'love_kernels', 'format', 'Boolean')
        WriteData(fid, prefix, 'object', self, 'fieldname', 'forcing_type', 'format', 'Integer')
    # }}}
