from ctypes import Structure, c_double, c_int
from operator import indexOf
import re

from define import CONNEX, LAYERS, NEURONS


class BrainStruct(Structure):
  _aignment_ = 16

  def __init__(self, nnw_name: str):
    with open(nnw_name) as f:
      step = 1
      line = ''
      if not f.readline().startswith('NNW'):
        print("Not a NNW Table")
        return
      line = f.readline()
      m = n = 0
      while (line):
        if line[0] != '#' and line[0] != '\n':
          # print(line)
          match step:
            case 1:
              info = line.split(" ")
              self.layersnb = int(info[1])
              for i in range(self.layersnb):
                self.nn[i] = int(info[i+2])
              # print(self.nn[0], self.nn[1], self.nn[2])
              step += 1
            case 2:
              info = re.findall(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?', line)
              for i in range(self.nn[0]):
                self.inbias[i] = float(info[i])
              step += 1
            case 3:
              for i in range(self.nn[0]):
                info = re.findall(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?', line)
                self.inscale[i] = float(info[i])
              step += 1
            case 4:
              info_list = [re.findall(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?', line)]
              for i in range(self.nn[0] - 1):
                info_list.append(re.findall(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?', f.readline()))
              for m in range(self.layersnb - 1):
                for k in range(self.nn[m]):
                  for z in range(self.nn[m]):
                    self.w[m][k][z] = float(info_list[z][k])
                  self.b[m][k] = float(info_list[k][-1])
                
                if m != self.layersnb - 2:
                  f.readline() # 空行
                  info_list = [re.findall(r'[-+]?\d*\.?\d+(?:[eE][-+]?\d+)?', f.readline())]
                  for i in range(self.nn[0] - 1):
                    info_list.append([0.0 for j in range(self.nn[m]+1)])

              step += 1
            case 5:
              for i in range(self.nn[self.layersnb - 1]):
                info = [line.lstrip().split(" ")[0]]
                for i in range(NEURONS - len(info)):
                  info.append(0.0)
                  self.outbias[i] = float(info[i])
              
              step += 1
            case 6:
              for i in range(self.nn[self.layersnb - 1]):
                info = [line.lstrip().split(" ")[0]]
                for i in range(NEURONS - len(info)):
                  info.append(0.0)
                  self.outscale[i] = float(info[i])
              step += 1
          
        line = f.readline()

BrainStruct._fields_ = [
  ("layersnb", c_int),
  ("nn", c_int * LAYERS),
  ("inbias", c_double * NEURONS),
  ("inscale", c_double * NEURONS),
  ("outbias", c_double * NEURONS),
  ("outscale", c_double * NEURONS),
  ("ni", c_double * NEURONS),
  ("no", c_double * NEURONS),
  ("n", (c_double * NEURONS) * LAYERS),
  ("w", ((c_double * NEURONS) * NEURONS) * CONNEX),
  ("b", (c_double * NEURONS) * CONNEX),
]