"use strict";

function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }

function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }

function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }

function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }

function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }

function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }

var _ = require('../../../utils/under-dash');

var colCache = require('../../../utils/col-cache');

var XmlStream = require('../../../utils/xml-stream');

var RelType = require('../../rel-type');

var Merges = require('./merges');

var BaseXform = require('../base-xform');

var ListXform = require('../list-xform');

var RowXform = require('./row-xform');

var ColXform = require('./col-xform');

var DimensionXform = require('./dimension-xform');

var HyperlinkXform = require('./hyperlink-xform');

var MergeCellXform = require('./merge-cell-xform');

var DataValidationsXform = require('./data-validations-xform');

var SheetPropertiesXform = require('./sheet-properties-xform');

var SheetFormatPropertiesXform = require('./sheet-format-properties-xform');

var SheetViewXform = require('./sheet-view-xform');

var SheetProtectionXform = require('./sheet-protection-xform');

var PageMarginsXform = require('./page-margins-xform');

var PageSetupXform = require('./page-setup-xform');

var PrintOptionsXform = require('./print-options-xform');

var AutoFilterXform = require('./auto-filter-xform');

var PictureXform = require('./picture-xform');

var DrawingXform = require('./drawing-xform');

var TablePartXform = require('./table-part-xform');

var RowBreaksXform = require('./row-breaks-xform');

var HeaderFooterXform = require('./header-footer-xform');

var ConditionalFormattingsXform = require('./cf/conditional-formattings-xform');

var WorkSheetXform =
/*#__PURE__*/
function (_BaseXform) {
  _inherits(WorkSheetXform, _BaseXform);

  function WorkSheetXform(options) {
    var _this;

    _classCallCheck(this, WorkSheetXform);

    _this = _possibleConstructorReturn(this, _getPrototypeOf(WorkSheetXform).call(this));

    var _ref = options || {},
        maxRows = _ref.maxRows,
        maxCols = _ref.maxCols;

    _this.map = {
      sheetPr: new SheetPropertiesXform(),
      dimension: new DimensionXform(),
      sheetViews: new ListXform({
        tag: 'sheetViews',
        count: false,
        childXform: new SheetViewXform()
      }),
      sheetFormatPr: new SheetFormatPropertiesXform(),
      cols: new ListXform({
        tag: 'cols',
        count: false,
        childXform: new ColXform()
      }),
      sheetData: new ListXform({
        tag: 'sheetData',
        count: false,
        empty: true,
        childXform: new RowXform({
          maxItems: maxCols
        }),
        maxItems: maxRows
      }),
      autoFilter: new AutoFilterXform(),
      mergeCells: new ListXform({
        tag: 'mergeCells',
        count: true,
        childXform: new MergeCellXform()
      }),
      rowBreaks: new RowBreaksXform(),
      hyperlinks: new ListXform({
        tag: 'hyperlinks',
        count: false,
        childXform: new HyperlinkXform()
      }),
      pageMargins: new PageMarginsXform(),
      dataValidations: new DataValidationsXform(),
      pageSetup: new PageSetupXform(),
      headerFooter: new HeaderFooterXform(),
      printOptions: new PrintOptionsXform(),
      picture: new PictureXform(),
      drawing: new DrawingXform(),
      sheetProtection: new SheetProtectionXform(),
      tableParts: new ListXform({
        tag: 'tableParts',
        count: true,
        childXform: new TablePartXform()
      }),
      conditionalFormatting: new ConditionalFormattingsXform()
    };
    return _this;
  }

  _createClass(WorkSheetXform, [{
    key: "prepare",
    value: function prepare(model, options) {
      options.merges = new Merges();
      model.hyperlinks = options.hyperlinks = [];
      model.comments = options.comments = [];
      options.formulae = {};
      options.siFormulae = 0;
      this.map.cols.prepare(model.cols, options);
      this.map.sheetData.prepare(model.rows, options);
      this.map.conditionalFormatting.prepare(model.conditionalFormattings, options);
      model.mergeCells = options.merges.mergeCells; // prepare relationships

      var rels = model.rels = [];

      function nextRid(r) {
        return "rId".concat(r.length + 1);
      }

      model.hyperlinks.forEach(function (hyperlink) {
        var rId = nextRid(rels);
        hyperlink.rId = rId;
        rels.push({
          Id: rId,
          Type: RelType.Hyperlink,
          Target: hyperlink.target,
          TargetMode: 'External'
        });
      }); // prepare comment relationships

      if (model.comments.length > 0) {
        var comment = {
          Id: nextRid(rels),
          Type: RelType.Comments,
          Target: "../comments".concat(model.id, ".xml")
        };
        rels.push(comment);
        var vmlDrawing = {
          Id: nextRid(rels),
          Type: RelType.VmlDrawing,
          Target: "../drawings/vmlDrawing".concat(model.id, ".vml")
        };
        rels.push(vmlDrawing);
        model.comments.forEach(function (item) {
          item.refAddress = colCache.decodeAddress(item.ref);
        });
        options.commentRefs.push({
          commentName: "comments".concat(model.id),
          vmlDrawing: "vmlDrawing".concat(model.id)
        });
      }

      var drawingRelsHash = [];
      var bookImage;
      model.media.forEach(function (medium) {
        if (medium.type === 'background') {
          var rId = nextRid(rels);
          bookImage = options.media[medium.imageId];
          rels.push({
            Id: rId,
            Type: RelType.Image,
            Target: "../media/".concat(bookImage.name, ".").concat(bookImage.extension)
          });
          model.background = {
            rId: rId
          };
          model.image = options.media[medium.imageId];
        } else if (medium.type === 'image') {
          var drawing = model.drawing;
          bookImage = options.media[medium.imageId];

          if (!drawing) {
            drawing = model.drawing = {
              rId: nextRid(rels),
              name: "drawing".concat(++options.drawingsCount),
              anchors: [],
              rels: []
            };
            options.drawings.push(drawing);
            rels.push({
              Id: drawing.rId,
              Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/drawing',
              Target: "../drawings/".concat(drawing.name, ".xml")
            });
          }

          var rIdImage = drawingRelsHash[medium.imageId];

          if (!rIdImage) {
            rIdImage = nextRid(drawing.rels);
            drawingRelsHash[medium.imageId] = rIdImage;
            drawing.rels.push({
              Id: rIdImage,
              Type: 'http://schemas.openxmlformats.org/officeDocument/2006/relationships/image',
              Target: "../media/".concat(bookImage.name, ".").concat(bookImage.extension)
            });
          }

          drawing.anchors.push({
            picture: {
              rId: rIdImage
            },
            range: medium.range
          });
        }
      }); // prepare tables

      model.tables.forEach(function (table) {
        // relationships
        var rId = nextRid(rels);
        table.rId = rId;
        rels.push({
          Id: rId,
          Type: RelType.Table,
          Target: "../tables/".concat(table.target)
        }); // dynamic styles

        table.columns.forEach(function (column) {
          var style = column.style;

          if (style) {
            column.dxfId = options.styles.addDxfStyle(style);
          }
        });
      });
    }
  }, {
    key: "render",
    value: function render(xmlStream, model) {
      xmlStream.openXml(XmlStream.StdDocAttributes);
      xmlStream.openNode('worksheet', WorkSheetXform.WORKSHEET_ATTRIBUTES);
      var sheetFormatPropertiesModel = model.properties ? {
        defaultRowHeight: model.properties.defaultRowHeight,
        dyDescent: model.properties.dyDescent,
        outlineLevelCol: model.properties.outlineLevelCol,
        outlineLevelRow: model.properties.outlineLevelRow
      } : undefined;
      var sheetPropertiesModel = {
        outlineProperties: model.properties && model.properties.outlineProperties,
        tabColor: model.properties && model.properties.tabColor,
        pageSetup: model.pageSetup && model.pageSetup.fitToPage ? {
          fitToPage: model.pageSetup.fitToPage
        } : undefined
      };
      var pageMarginsModel = model.pageSetup && model.pageSetup.margins;
      var printOptionsModel = {
        showRowColHeaders: model.showRowColHeaders,
        showGridLines: model.showGridLines,
        horizontalCentered: model.horizontalCentered,
        verticalCentered: model.verticalCentered
      };
      var sheetProtectionModel = model.sheetProtection;
      this.map.sheetPr.render(xmlStream, sheetPropertiesModel);
      this.map.dimension.render(xmlStream, model.dimensions);
      this.map.sheetViews.render(xmlStream, model.views);
      this.map.sheetFormatPr.render(xmlStream, sheetFormatPropertiesModel);
      this.map.cols.render(xmlStream, model.cols);
      this.map.sheetData.render(xmlStream, model.rows);
      this.map.sheetProtection.render(xmlStream, sheetProtectionModel); // Note: must be after sheetData and before autoFilter

      this.map.autoFilter.render(xmlStream, model.autoFilter);
      this.map.mergeCells.render(xmlStream, model.mergeCells);
      this.map.dataValidations.render(xmlStream, model.dataValidations); // For some reason hyperlinks have to be after the data validations

      this.map.hyperlinks.render(xmlStream, model.hyperlinks);
      this.map.conditionalFormatting.render(xmlStream, model.conditionalFormattings);
      this.map.pageMargins.render(xmlStream, pageMarginsModel);
      this.map.printOptions.render(xmlStream, printOptionsModel);
      this.map.pageSetup.render(xmlStream, model.pageSetup);
      this.map.headerFooter.render(xmlStream, model.headerFooter);
      this.map.rowBreaks.render(xmlStream, model.rowBreaks);
      this.map.drawing.render(xmlStream, model.drawing); // Note: must be after rowBreaks

      this.map.picture.render(xmlStream, model.background); // Note: must be after drawing

      this.map.tableParts.render(xmlStream, model.tables);

      if (model.rels) {
        // add a <legacyDrawing /> node for each comment
        model.rels.forEach(function (rel) {
          if (rel.Type === RelType.VmlDrawing) {
            xmlStream.leafNode('legacyDrawing', {
              'r:id': rel.Id
            });
          }
        });
      }

      xmlStream.closeNode();
    }
  }, {
    key: "parseOpen",
    value: function parseOpen(node) {
      if (this.parser) {
        this.parser.parseOpen(node);
        return true;
      }

      if (node.name === 'worksheet') {
        _.each(this.map, function (xform) {
          xform.reset();
        });

        return true;
      }

      this.parser = this.map[node.name];

      if (this.parser) {
        this.parser.parseOpen(node);
      }

      return true;
    }
  }, {
    key: "parseText",
    value: function parseText(text) {
      if (this.parser) {
        this.parser.parseText(text);
      }
    }
  }, {
    key: "parseClose",
    value: function parseClose(name) {
      if (this.parser) {
        if (!this.parser.parseClose(name)) {
          this.parser = undefined;
        }

        return true;
      }

      switch (name) {
        case 'worksheet':
          {
            var properties = this.map.sheetFormatPr.model;

            if (this.map.sheetPr.model && this.map.sheetPr.model.tabColor) {
              properties.tabColor = this.map.sheetPr.model.tabColor;
            }

            if (this.map.sheetPr.model && this.map.sheetPr.model.outlineProperties) {
              properties.outlineProperties = this.map.sheetPr.model.outlinePropertiesx;
            }

            var sheetProperties = {
              fitToPage: this.map.sheetPr.model && this.map.sheetPr.model.pageSetup && this.map.sheetPr.model.pageSetup.fitToPage || false,
              margins: this.map.pageMargins.model
            };
            var pageSetup = Object.assign(sheetProperties, this.map.pageSetup.model, this.map.printOptions.model);
            this.model = {
              dimensions: this.map.dimension.model,
              cols: this.map.cols.model,
              rows: this.map.sheetData.model,
              mergeCells: this.map.mergeCells.model,
              hyperlinks: this.map.hyperlinks.model,
              dataValidations: this.map.dataValidations.model,
              properties: properties,
              views: this.map.sheetViews.model,
              pageSetup: pageSetup,
              headerFooter: this.map.headerFooter.model,
              background: this.map.picture.model,
              drawing: this.map.drawing.model,
              tables: this.map.tableParts.model,
              conditionalFormattings: this.map.conditionalFormatting.model
            };

            if (this.map.autoFilter.model) {
              this.model.autoFilter = this.map.autoFilter.model;
            }

            if (this.map.sheetProtection.model) {
              this.model.sheetProtection = this.map.sheetProtection.model;
            }

            return false;
          }

        default:
          // not quite sure how we get here!
          return true;
      }
    }
  }, {
    key: "reconcile",
    value: function reconcile(model, options) {
      // options.merges = new Merges();
      // options.merges.reconcile(model.mergeCells, model.rows);
      var rels = (model.relationships || []).reduce(function (h, rel) {
        h[rel.Id] = rel;

        if (rel.Type === RelType.Comments) {
          model.comments = options.comments[rel.Target].comments;
        }

        return h;
      }, {});
      options.commentsMap = (model.comments || []).reduce(function (h, comment) {
        if (comment.ref) {
          h[comment.ref] = comment;
        }

        return h;
      }, {});
      options.hyperlinkMap = (model.hyperlinks || []).reduce(function (h, hyperlink) {
        if (hyperlink.rId) {
          h[hyperlink.address] = rels[hyperlink.rId].Target;
        }

        return h;
      }, {});
      options.formulae = {}; // compact the rows and cells

      model.rows = model.rows && model.rows.filter(Boolean) || [];
      model.rows.forEach(function (row) {
        row.cells = row.cells && row.cells.filter(Boolean) || [];
      });
      this.map.cols.reconcile(model.cols, options);
      this.map.sheetData.reconcile(model.rows, options);
      this.map.conditionalFormatting.reconcile(model.conditionalFormattings, options);
      model.media = [];

      if (model.drawing) {
        var drawingRel = rels[model.drawing.rId];
        var match = drawingRel.Target.match(/\/drawings\/([a-zA-Z0-9]+)[.][a-zA-Z]{3,4}$/);

        if (match) {
          var drawingName = match[1];
          var drawing = options.drawings[drawingName];
          drawing.anchors.forEach(function (anchor) {
            if (anchor.medium) {
              var image = {
                type: 'image',
                imageId: anchor.medium.index,
                range: anchor.range
              };
              model.media.push(image);
            }
          });
        }
      }

      var backgroundRel = model.background && rels[model.background.rId];

      if (backgroundRel) {
        var target = backgroundRel.Target.split('/media/')[1];
        var imageId = options.mediaIndex && options.mediaIndex[target];

        if (imageId !== undefined) {
          model.media.push({
            type: 'background',
            imageId: imageId
          });
        }
      }

      model.tables = (model.tables || []).map(function (tablePart) {
        var rel = rels[tablePart.rId];
        return options.tables[rel.Target];
      });
      delete model.relationships;
      delete model.hyperlinks;
      delete model.comments;
    }
  }]);

  return WorkSheetXform;
}(BaseXform);

WorkSheetXform.WORKSHEET_ATTRIBUTES = {
  xmlns: 'http://schemas.openxmlformats.org/spreadsheetml/2006/main',
  'xmlns:r': 'http://schemas.openxmlformats.org/officeDocument/2006/relationships',
  'xmlns:mc': 'http://schemas.openxmlformats.org/markup-compatibility/2006',
  'mc:Ignorable': 'x14ac',
  'xmlns:x14ac': 'http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac'
};
module.exports = WorkSheetXform;
//# sourceMappingURL=worksheet-xform.js.map
