import numpy as np

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


class giamme(object):
    """GIAMME class definition

    Usage:
        gia = giamme() #gia class based on a multi-model ensemble (ex: Caron et al 2017 statistics)
    """

    def __init__(self, *args): #{{{
        self.modelid    = 0 #index into the multi-model ensemble
        self.Ngia       = [] #geoid ensemble
        self.Ugia       = [] #uplift ensemble
        
        nargin = len(args)

        if nargin == 0:
            self.setdefaultparameters()
        else:
            raise Exception('constructor not supported')
    #}}}

    def __repr__(self): # {{{
        s = '   gia mme parameters:\n'
        s += '{}\n'.format(fielddisplay(self, 'modelid', 'index into the multi-model ensemble, determines which field will be used.'))
        s += '{}\n'.format(fielddisplay(self, 'Ngia', 'geoid (mm/yr).'))
        s += '{}\n'.format(fielddisplay(self, 'Ugia', 'uplift (mm/yr).'))
        return s
    #}}}

    def setdefaultparameters(self): # {{{
        return self
    #}}}

    def checkconsistency(self, md, solution, analyses): # {{{
        if 'SealevelriseAnalysis' not in analyses:
            return md
        if solution == 'TransientSolution' and not md.transient.isslr:
            return md
        md = checkfield(md, 'field', self.Ngia, 'NaN', 1, 'Inf', 1)
        md = checkfield(md, 'field', self.Ugia, 'NaN', 1, 'Inf', 1)
        md = checkfield(md, 'field', self.modelid, 'NaN', 1, 'Inf', 1, '>=', 0, '<=', len(self.Ngia))
        return md
    #}}}

    def marshall(self, prefix, md, fid): #{{{
        WriteData(fid, prefix, 'name', 'md.gia.model', 'data', 3, 'format', 'Integer')

        if isinstance(self.Ngia, list) or self.Ngia.ndim == 1: #list or 1D numpy.ndarray
            WriteData(fid, prefix, 'data', np.zeros((md.mesh.numberofvertices, 1)), 'format', 'DoubleMat', 'mattype', 1, 'name', 'md.gia.Ngia')
            WriteData(fid, prefix, 'data', np.zeros((md.mesh.numberofvertices, 1)), 'format', 'DoubleMat', 'mattype', 1, 'name', 'md.gia.Ugia')
            WriteData(fid, prefix, 'data', 1, 'name', 'md.gia.modelid', 'format', 'Double')
            WriteData(fid, prefix, 'name', 'md.gia.nummodels', 'data', 1, 'format', 'Integer')
        else: #2D numpy.ndarray
            WriteData(fid, prefix, 'object ', self, 'fieldname', 'Ngia', 'format', 'DoubleMat', 'scale', 1 / 1000 / md.constants.yts)
            WriteData(fid, prefix, 'object ', self, 'fieldname', 'Ugia', 'format', 'DoubleMat', 'scale', 1 / 1000 / md.constants.yts)
            WriteData(fid, prefix, 'object ', self, 'fieldname', 'modelid', 'format', 'Double')
            WriteData(fid, prefix, 'name', 'md.gia.nummodels', 'data', self.Ngia.shape[1],'format', 'Integer') #NOTE: <<numpy.ndarray>>.shape[1] gives length of second dimension
    #}}}

    def extrude(self, md): #{{{
        for i in range(len(self.Ngia)):
            self.Ngia[i] = project3d(md, 'vector', self.Ngia[i], 'type', 'node', 'layer', 1)
            self.Ugia[i] = project3d(md, 'vector', self.Ugia[i], 'type', 'node', 'layer', 1)
        return self
    #}}}
