"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "DifferBasedRendererAdapter", {
    enumerable: true,
    get: function() {
        return DifferBasedRendererAdapter;
    }
});
const _constants = require("../constants");
class DifferBasedRendererAdapter {
    /**
   * Applies the commands generated by the differ into the specific DOM operations.
   *
   * @param {Array} command The command to apply.
   */ applyCommand(command) {
        const { rootNode } = this.orderView;
        const [name, nodeIndex, nodePrevIndex, nodeIndexToRemove] = command;
        const node = this.orderView.nodesPool(nodeIndex);
        this.orderView.collectedNodes.push(node);
        switch(name){
            case _constants.CMD_PREPEND:
                rootNode.insertBefore(node, rootNode.firstChild);
                break;
            case _constants.CMD_APPEND:
                rootNode.appendChild(node);
                break;
            case _constants.CMD_INSERT_BEFORE:
                rootNode.insertBefore(node, this.orderView.nodesPool(nodePrevIndex));
                // To keep the constant length of child nodes (after inserting a node) remove the last child.
                rootNode.removeChild(this.orderView.nodesPool(nodeIndexToRemove));
                break;
            case _constants.CMD_REPLACE:
                rootNode.replaceChild(node, this.orderView.nodesPool(nodePrevIndex));
                break;
            case _constants.CMD_REMOVE:
                rootNode.removeChild(node);
                break;
            default:
                break;
        }
    }
    /**
   * Sets up and prepares all necessary properties and starts the rendering process.
   * This method has to be called only once (at the start) for the render cycle.
   */ start() {
        this.orderView.collectedNodes.length = 0;
        this.leads = this.orderView.viewDiffer.diff();
        this.leadIndex = 0;
    }
    /**
   * Renders the DOM element based on visual index (which is calculated internally).
   * This method has to be called as many times as the size count is met (to cover all previously rendered DOM elements).
   */ render() {
        if (this.leadIndex < this.leads.length) {
            this.applyCommand(this.leads[this.leadIndex]);
            this.leadIndex += 1;
        }
    }
    /**
   * Ends the render process.
   * This method has to be called only once (at the end) for the render cycle.
   */ end() {
        const { leads } = this;
        while(this.leadIndex < leads.length){
            this.applyCommand(leads[this.leadIndex]);
            this.leadIndex += 1;
        }
    }
    /**
   * @param {OrderView} orderView The OrderView instance.
   */ constructor(orderView){
        /**
   * The list of render commands to execute. The command is an array with the following
   * structure: [
   *   [
   *     CMD_PREPEND | CMD_APPEND | CMD_INSERT_BEFORE | CMD_REPLACE | CMD_REMOVE, // command type
   *     10, // processed node index
   *     9,  // previous node index (only for CMD_INSERT_BEFORE and CMD_REPLACE commands)
   *     8   // node index to remove (only for CMD_INSERT_BEFORE command)
   *   ],
   *   ...
   * ].
   *
   * @type {Array[]}
   */ this.leads = [];
        /**
   * Current position within the leads array. Used instead of Array.shift()
   * to avoid O(n) per-call overhead.
   *
   * @type {number}
   */ this.leadIndex = 0;
        this.orderView = orderView;
    }
}
