import {ResolvedPos} from "prosemirror-model";

/**
 * Determine whether a given position has an ancestor node of the given type.
 * @param {NodeType} other  The other node type.
 * @param {object} [attrs]  An object of attributes that must also match, if provided.
 * @returns {boolean}
 */
ResolvedPos.prototype.hasAncestor = function(other, attrs) {
  if ( !this.depth ) return false;
  for ( let i = this.depth; i > 0; i-- ) { // Depth 0 is the root document, so we don't need to test that.
    const node = this.node(i);
    if ( node.type === other ) {
      const nodeAttrs = foundry.utils.deepClone(node.attrs);
      delete nodeAttrs._preserve; // Do not include our internal attributes in the comparison.
      if ( attrs ) return Object.entries(attrs).every(([k, v]) => foundry.utils.equals(nodeAttrs[k], v));
      return true;
    }
  }
  return false;
};

/* -------------------------------------------- */

/**
 * Determine if this position is in the first node of the Document.
 * @this {ResolvedPos}
 * @returns {boolean}
 */
function isFirstNode() {
  let { depth } = this;
  while ( depth && !this.index(depth--) );
  return !depth;
}

/* -------------------------------------------- */

/**
 * Determine if this position is in the last node of the Document.
 * @this {ResolvedPos}
 * @returns {boolean}
 */
function isLastNode() {
  let { depth } = this;
  while ( depth-- ) {
    const parent = this.node(depth);
    const index = this.index(depth);
    if ( index < parent.childCount - 1 ) return false;
  }
  return true;
}

/* -------------------------------------------- */

Object.defineProperties(ResolvedPos.prototype, {
  isFirstNode: { get: isFirstNode },
  isLastNode: { get: isLastNode }
});
