# ----------------------------------------------------------------------------
#
#  Copyright (C) 2018-2022 Fons Adriaensen <fons@linuxaudio.org>
#    
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http:#www.gnu.org/licenses/>.
#
# ----------------------------------------------------------------------------


import array

class IoElm ():
    def __init__(self):
        self.reset ()
        
    def reset (self):
        self.gain = 0.0
        self.mute = 0
        
        
class IoVec ():
    def __init__ (self, nelm):
        self.nelm = nelm
        self.elms = [ IoElm () for i in range (nelm) ]

    def reset (self):
        for E in self.elms: E.reset ()

    def elem (self, elm):
        return self.elms [elm]

    def write (self, fobj):
        n = len (self.elms)
        for i in range (self.nelm):
            E = self.elms [i]
            f = ''
            if E.mute: f += 'M'
            if (E.gain == 0.0) and (f == ''): continue
            fobj.write ("%3d %6.1f %s\n" % (i, E.gain, f))

    def read (self, s):
        try:
            E = self.elms [int (s [0])]
            E.gain = float (s [1])
            if len (s) > 2:
                E.mute = 'M' in s [2]
        except:
            return

        
class MatElm ():
    def __init__ (self):
        self.reset ()

    def reset (self):
        self.gain = -200.0
        self.delay = 0.0
        self.inv = 0

        
class Matrix ():
    def __init__ (self, ninp, nout):
        n = ninp * nout
        self.ninp = ninp
        self.nout = nout
        self.elms = [ MatElm () for i in range (n) ]

    def reset (self):
        for E in self.elms: E.reset ()

    def elem (self, inp, out):
        return self.elms [out * self.ninp + inp]
        
    def write (self, fobj):
        for out in range (self.nout):
            for inp in range (self.ninp):
                E = self.elem (inp, out)
                f = ''
                if E.inv: f += 'I'
                if (E.gain <= -200.0) and (E.delay == 0) and (f == ''):
                    continue
                fobj.write ("%3d %3d %8.1f %5.1f %s\n"
                            % (inp, out, E.gain, E.delay, f))
            
    def read (self, s):
        try:
            E = self.elem (int (s [0]), int (s [1]))
            E.gain = float (s [2])
            E.delay = float (s [3])
            if len (s) > 4:
                E.inv = 'I' in s [4]
        except:
            return
                
                    
class Matrixstate ():

    def __init__ (self, ninp, nout):
        self.inpgain = IoVec (ninp)
        self.outgain = IoVec (nout)
        self.matrix = Matrix (ninp, nout)
        
    def reset (self):
        self.inpgain.reset ()
        self.outgain.reset ()
        self.matrix.reset ()
        
    def write (self, fobj):
        fobj.write ("INP\n")
        self.inpgain.write (fobj)
        fobj.write ("OUT\n")
        self.outgain.write (fobj)
        fobj.write ("MAT\n")
        self.matrix.write (fobj)
        fobj.write ("END\n")

    def read (self, fobj):
        self.reset ()
        sect = None
        while True:
            s = fobj.readline ()
            if len (s) == 0: return
            s = s.split ()
            if len (s) == 0: continue
            if   s [0] == 'INP': sect = self.inpgain
            elif s [0] == 'OUT': sect = self.outgain
            elif s [0] == 'MAT': sect = self.matrix
            elif s [0] == 'END': return
            elif sect is not None: sect.read (s)
        
