text: "use strict";
  /**
   * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
   *
   * @author Alexander Rose <alexander.rose@weirdbyte.de>
   */
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.parseDcd = exports._parseDcd = void 0;
  var tslib_1 = require("tslib");
  var result_1 = require("../result");
  var mol_task_1 = require("../../../mol-task");
  var binary_1 = require("../../common/binary");
  function _parseDcd(data) {
      // http://www.ks.uiuc.edu/Research/vmd/plugins/molfile/dcdplugin.html
      // The DCD format is structured as follows
      //   (FORTRAN UNFORMATTED, with Fortran data type descriptions):
      // HDR     NSET    ISTRT   NSAVC   5-ZEROS NATOM-NFREAT    DELTA   9-ZEROS
      // `CORD'  #files  step 1  step    zeroes  (zero)          timestep  (zeroes)
      //                         interval
      // C*4     INT     INT     INT     5INT    INT             DOUBLE  9INT
      // ==========================================================================
      // NTITLE          TITLE
      // INT (=2)        C*MAXTITL
      //                 (=32)
      // ==========================================================================
      // NATOM
      // #atoms
      // INT
      // ==========================================================================
      // X(I), I=1,NATOM         (DOUBLE)
      // Y(I), I=1,NATOM
      // Z(I), I=1,NATOM
      // ==========================================================================
      var dv = new DataView(data.buffer);
      var header = Object.create(null);
      var frames = [];
      var nextPos = 0;
      // header block
      var intView = new Int32Array(data.buffer, 0, 23);
      var ef = intView[0] !== dv.getInt32(0); // endianess flag
      // swap byte order when big endian (84 indicates little endian)
      if (intView[0] !== 84) {
          var n = data.byteLength;
          for (var i = 0; i < n; i += 4) {
              dv.setFloat32(i, dv.getFloat32(i), true);
          }
      }
      if (intView[0] !== 84) {
          throw new Error('dcd bad format, header block start');
      }
      // format indicator, should read 'CORD'
      var formatString = String.fromCharCode(dv.getUint8(4), dv.getUint8(5), dv.getUint8(6), dv.getUint8(7));
      if (formatString !== 'CORD') {
          throw new Error('dcd bad format, format string');
      }
      var isCharmm = false;
      var extraBlock = false;
      var fourDims = false;
      // version field in charmm, unused in X-PLOR
      if (intView[22] !== 0) {
          isCharmm = true;
          if (intView[12] !== 0)
              extraBlock = true;
          if (intView[13] === 1)
              fourDims = true;
      }
      header.NSET = intView[2];
      header.ISTART = intView[3];
      header.NSAVC = intView[4];
      header.NAMNF = intView[10];
      if (isCharmm) {
          header.DELTA = dv.getFloat32(44, ef);
      }
      else {
          header.DELTA = dv.getFloat64(44, ef);
      }
      if (intView[22] !== 84) {
          throw new Error('dcd bad format, header block end');
      }
      nextPos = nextPos + 21 * 4 + 8;
      // title block
      var titleEnd = dv.getInt32(nextPos, ef);
      var titleStart = nextPos + 1;
      if ((titleEnd - 4) % 80 !== 0) {
          throw new Error('dcd bad format, title block start');
      }
      header.TITLE = (0, binary_1.uint8ToString)(data.subarray(titleStart, titleEnd));
      if (dv.getInt32(titleStart + titleEnd + 4 - 1, ef) !== titleEnd) {
          throw new Error('dcd bad format, title block end');
      }
      nextPos = nextPos + titleEnd + 8;
      // natom block
      if (dv.getInt32(nextPos, ef) !== 4) {
          throw new Error('dcd bad format, natom block start');
      }
      header.NATOM = dv.getInt32(nextPos + 4, ef);
      if (dv.getInt32(nextPos + 8, ef) !== 4) {
          throw new Error('dcd bad format, natom block end');
      }
      nextPos = nextPos + 4 + 8;
      // fixed atoms block
      if (header.NAMNF > 0) {
          // TODO read coordinates and indices of fixed atoms
          throw new Error('dcd format with fixed atoms unsupported, aborting');
      }
      // frames
      var natom = header.NATOM;
      var natom4 = natom * 4;
      for (var i = 0, n = header.NSET; i < n; ++i) {
          var frame = Object.create(null);
          frame.elementCount = natom;
          if (extraBlock) {
              nextPos += 4; // block start
              frame.cell = [
                  dv.getFloat64(nextPos, ef),
                  dv.getFloat64(nextPos + 1, ef),
                  dv.getFloat64(nextPos + 2 * 8, ef),
                  dv.getFloat64(nextPos + 3 * 8, ef),
                  dv.getFloat64(nextPos + 4 * 8, ef),
                  dv.getFloat64(nextPos + 5 * 8, ef)
              ];
              nextPos += 48;
              nextPos += 4; // block end
          }
          // xyz coordinates
          for (var j = 0; j < 3; ++j) {
              if (dv.getInt32(nextPos, ef) !== natom4) {
                  throw new Error("dcd bad format, coord block start: ".concat(i, ", ").concat(j));
              }
              nextPos += 4; // block start
              var c = new Float32Array(data.buffer, nextPos, natom);
              if (j === 0)
                  frame.x = c;
              else if (j === 1)
                  frame.y = c;
              else
                  frame.z = c;
              nextPos += natom4;
              if (dv.getInt32(nextPos, ef) !== natom4) {
                  throw new Error("dcd bad format, coord block end: ".concat(i, ", ").concat(j));
              }
              nextPos += 4; // block end
          }
          if (fourDims) {
              var bytes = dv.getInt32(nextPos, ef);
              nextPos += 4 + bytes + 4; // block start + skip + block end
          }
          frames.push(frame);
      }
      return { header: header, frames: frames };
  }
  exports._parseDcd = _parseDcd;
  function parseDcd(data) {
      var _this = this;
      return mol_task_1.Task.create('Parse DCD', function (ctx) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
          var dcdFile;
          return (0, tslib_1.__generator)(this, function (_a) {
              try {
                  dcdFile = _parseDcd(data);
                  return [2 /*return*/, result_1.ReaderResult.success(dcdFile)];
              }
              catch (e) {
                  return [2 /*return*/, result_1.ReaderResult.error(e)];
              }
              return [2 /*return*/];
          });
      }); });
  }
  exports.parseDcd = parseDcd;
  //# sourceMappingURL=parser.js.map