"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getCustomStyleCommands = getCustomStyleCommands;
exports.updateOverrideFlag = updateOverrideFlag;
exports.applyLatestStyle = applyLatestStyle;
exports.applyStyle = applyStyle;
exports.getNode = getNode;
exports.default = exports.NUMBERING = exports.INDENT = exports.ATTR_OVERRIDDEN = exports.SBEFORE = exports.SAFTER = exports.NONE = exports.LHEIGHT = exports.ALIGN = exports.UNDERLINE = exports.TEXTHL = exports.SUPER = exports.STRIKE = exports.FONTNAME = exports.FONTSIZE = exports.COLOR = exports.EM = exports.STRONG = void 0;

var _prosemirrorState = require("prosemirror-state");

var _prosemirrorTransform = require("prosemirror-transform");

var _prosemirrorView = require("prosemirror-view");

var _prosemirrorModel = require("prosemirror-model");

var _UICommand = _interopRequireDefault(require("./ui/UICommand"));

var _PopUpPosition = require("./ui/PopUpPosition");

var _createPopUp = _interopRequireDefault(require("./ui/createPopUp"));

var _CustomStyleEditor = _interopRequireDefault(require("./ui/CustomStyleEditor"));

var _MarkToggleCommand = _interopRequireDefault(require("./MarkToggleCommand"));

var _TextColorCommand = _interopRequireDefault(require("./TextColorCommand"));

var _TextHighlightCommand = _interopRequireDefault(require("./TextHighlightCommand"));

var _TextAlignCommand = _interopRequireWildcard(require("./TextAlignCommand"));

var _FontTypeCommand = _interopRequireDefault(require("./FontTypeCommand"));

var _FontSizeCommand = _interopRequireDefault(require("./FontSizeCommand"));

var _TextLineSpacingCommand = _interopRequireDefault(require("./TextLineSpacingCommand"));

var _ParagraphSpacingCommand = _interopRequireDefault(require("./ParagraphSpacingCommand"));

var _IndentCommand = _interopRequireDefault(require("./IndentCommand"));

var _ListToggleCommand = _interopRequireDefault(require("./ListToggleCommand"));

var _clearCustomStyleMarks = require("./clearCustomStyleMarks");

var _customStyle = require("./customStyle");

var _MarkNames = require("./MarkNames");

var _toCSSLineSpacing = require("./ui/toCSSLineSpacing");

function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

const STRONG = 'strong';
exports.STRONG = STRONG;
const EM = 'em';
exports.EM = EM;
const COLOR = 'color';
exports.COLOR = COLOR;
const FONTSIZE = 'fontsize';
exports.FONTSIZE = FONTSIZE;
const FONTNAME = 'fontname';
exports.FONTNAME = FONTNAME;
const STRIKE = 'strike';
exports.STRIKE = STRIKE;
const SUPER = 'super';
exports.SUPER = SUPER;
const TEXTHL = 'texthighlight';
exports.TEXTHL = TEXTHL;
const UNDERLINE = 'underline';
exports.UNDERLINE = UNDERLINE;
const ALIGN = 'align';
exports.ALIGN = ALIGN;
const LHEIGHT = 'lineheight';
exports.LHEIGHT = LHEIGHT;
const NONE = 'None';
exports.NONE = NONE;
const SAFTER = 'spaceafter';
exports.SAFTER = SAFTER;
const SBEFORE = 'spacebefore';
exports.SBEFORE = SBEFORE;
const ATTR_OVERRIDDEN = 'overridden';
exports.ATTR_OVERRIDDEN = ATTR_OVERRIDDEN;
const INDENT = 'indent';
exports.INDENT = INDENT;
const NUMBERING = 'hasnumbering'; // [FS] IRAD-1042 2020-10-01
// Creates commands based on custom style JSon object

exports.NUMBERING = NUMBERING;

function getCustomStyleCommands(customStyle) {
  const commands = [];

  for (const property in customStyle) {
    switch (property) {
      case STRONG:
        // [FS] IRAD-1043 2020-10-23
        // Issue fix : unselect a style when creating a new style
        // and that unselected styles also applied in selected paragraph
        if (customStyle[property]) commands.push(new _MarkToggleCommand.default('strong'));
        break;

      case EM:
        // [FS] IRAD-1043 2020-10-23
        // Issue fix : unselect a style when creating a new style
        // and that unselected styles also applied in selected paragrapgh
        if (customStyle[property]) commands.push(new _MarkToggleCommand.default('em'));
        break;

      case COLOR:
        commands.push(new _TextColorCommand.default(customStyle[property]));
        break;

      case FONTSIZE:
        commands.push(new _FontSizeCommand.default(Number(customStyle[property])));
        break;

      case FONTNAME:
        commands.push(new _FontTypeCommand.default(customStyle[property]));
        break;

      case STRIKE:
        // [FS] IRAD-1043 2020-10-23
        // Issue fix : unselect a style when creating a new style
        // and that unselected styles also applied in selected paragrapgh
        if (customStyle[property]) commands.push(new _MarkToggleCommand.default('strike'));
        break;

      case SUPER:
        commands.push(new _MarkToggleCommand.default('super'));
        break;

      case TEXTHL:
        commands.push(new _TextHighlightCommand.default(customStyle[property]));
        break;

      case UNDERLINE:
        commands.push(new _MarkToggleCommand.default('underline'));
        break;

      case ALIGN:
        commands.push(new _TextAlignCommand.default(customStyle[property]));
        break;

      case LHEIGHT:
        commands.push(new _TextLineSpacingCommand.default(customStyle[property]));
        break;
      // [FS] IRAD-1100 2020-11-05
      // Add in leading and trailing spacing (before and after a paragraph)

      case SAFTER:
        commands.push(new _ParagraphSpacingCommand.default(customStyle[property], true));
        break;

      case SBEFORE:
        commands.push(new _ParagraphSpacingCommand.default(customStyle[property], false));
        break;

      case INDENT:
        commands.push(new _IndentCommand.default(customStyle[property]));
        break;

      case NUMBERING:
        commands.push(new _ListToggleCommand.default(true, 'x.x.x'));
        break;

      default:
        break;
    }
  }

  return commands;
}

class CustomStyleCommand extends _UICommand.default {
  constructor(customStyle, customStyleName) {
    super();

    _defineProperty(this, "_customStyleName", void 0);

    _defineProperty(this, "_customStyle", []);

    _defineProperty(this, "_popUp", null);

    _defineProperty(this, "renderLabel", state => {
      return this._customStyleName;
    });

    _defineProperty(this, "getTheInlineStyles", isInline => {
      let attrs = {};
      let propsCopy = [];
      propsCopy = Object.assign(propsCopy, this._customStyle);
      propsCopy.forEach(style => {
        attrs = Object.assign(attrs, style);
        Object.entries(style).forEach((_ref) => {
          let [key, value] = _ref;

          if (isInline && typeof value === 'boolean') {
            delete attrs[key];
          } else if (!isInline && typeof value != 'boolean') {
            delete attrs[key];
          }
        });
      });
      return attrs;
    });

    _defineProperty(this, "isEmpty", obj => {
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          return false;
        }
      }

      return true;
    });

    _defineProperty(this, "isEnabled", (state, view, menuTitle) => {
      // [FS] IRAD-1053 2020-10-22
      // Disable the Clear style menu when no styles applied to a paragraph
      return !('clearstyle' == menuTitle && NONE == this.isCustomStyleApplied(state));
    });

    _defineProperty(this, "execute", (state, dispatch, view) => {
      let {
        tr
      } = state;
      const {
        selection
      } = state;

      if ('newstyle' === this._customStyle) {
        this.editWindow(state, view);
        return false;
      } // [FS] IRAD-1053 2020-10-08
      // to remove the custom styles applied in the selected paragraph
      else if ('clearstyle' === this._customStyle) {
          tr = (0, _clearCustomStyleMarks.clearCustomStyleMarks)(state.tr.setSelection(selection), state.schema, state);

          if (dispatch && tr.docChanged) {
            dispatch(tr);
            return true;
          }

          return false;
        }

      tr = applyStyle(this._customStyle.styles, this._customStyle.stylename, state, tr);

      if (tr.docChanged || tr.storedMarksSet) {
        dispatch && dispatch(tr);
        return true;
      }

      return false;
    });

    this._customStyle = customStyle;
    this._customStyleName = customStyleName;
  }

  // [FS] IRAD-1053 2020-10-22
  // returns the applied style of a paragraph
  isCustomStyleApplied(editorState) {
    const {
      selection,
      doc
    } = editorState;
    const {
      from,
      to
    } = selection;
    let customStyleName = NONE;
    doc.nodesBetween(from, to, (node, pos) => {
      if (node.attrs.styleName) {
        customStyleName = node.attrs.styleName;
      }
    });
    return customStyleName;
  }

  // shows the create style popup
  editWindow(state, view) {
    const {
      dispatch
    } = view;
    let tr = state.tr;
    const doc = state.doc;
    this._popUp = (0, _createPopUp.default)(_CustomStyleEditor.default, this.createCustomObject(), {
      autoDismiss: false,
      position: _PopUpPosition.atViewportCenter,
      onClose: val => {
        if (this._popUp) {
          this._popUp = null; //handle save style object part here

          if (undefined !== val) {
            console.log(val);
            this.saveStyleObject(val);
            tr = tr.setSelection(_prosemirrorState.TextSelection.create(doc, 0, 0)); // Apply created styles to document

            tr = applyStyle(val.styles, val.stylename, state, tr);
            dispatch(tr);
            view.focus();
          }
        }
      }
    });
  } // creates a sample style object


  createCustomObject() {
    return {
      stylename: '',
      styles: {}
    };
  } // locally save style object


  saveStyleObject(style) {
    (0, _customStyle.saveStyle)(style);
  }

}

function compareMarkWithStyle(mark, style, tr, startPos, endPos, retObj) {
  let same = false;
  let overridden = false;

  switch (mark.type.name) {
    case _MarkNames.MARK_STRONG:
      same = undefined != style[STRONG];
      break;

    case _MarkNames.MARK_EM:
      same = undefined != style[EM];
      break;

    case _MarkNames.MARK_TEXT_COLOR:
      same = mark.attrs['color'] == style[COLOR];
      break;

    case _MarkNames.MARK_FONT_SIZE:
      same = mark.attrs['pt'] == style[FONTSIZE];
      break;

    case _MarkNames.MARK_FONT_TYPE:
      same = mark.attrs['name'] == style[FONTNAME];
      break;

    case _MarkNames.MARK_STRIKE:
      same = undefined != style[STRIKE];
      break;

    case _MarkNames.MARK_SUPER:
      break;

    case _MarkNames.MARK_TEXT_HIGHLIGHT:
      break;

    case _MarkNames.MARK_UNDERLINE:
      same = undefined != style[UNDERLINE];
      break;

    default:
      break;
  }

  overridden = !same;

  if (undefined != mark.attrs[ATTR_OVERRIDDEN] && mark.attrs[ATTR_OVERRIDDEN] != overridden && tr.curSelection) {
    mark.attrs[ATTR_OVERRIDDEN] = overridden;
    tr = tr.removeMark(startPos, endPos, mark);
    tr = tr.addMark(startPos, endPos, mark);
    retObj.modified = true;
  }
  /*
  case SUPER:
  case TEXTHL:
  case ALIGN:
  case LHEIGHT:*/


  return tr;
}

function updateOverrideFlag(styleName, tr, node, startPos, endPos, retObj) {
  const style = (0, _customStyle.getCustomStyleByName)(styleName);

  if (style) {
    node.descendants(function (child, pos, parent) {
      if (child instanceof _prosemirrorModel.Node) {
        child.marks.forEach(function (mark, index) {
          tr = compareMarkWithStyle(mark, style, tr, startPos, endPos, retObj);
        });
      }
    });
  }

  return tr;
}

function onLoadRemoveAllMarksExceptOverridden(node, schema, from, to, tr) {
  const tasks = [];
  node.descendants(function (child, pos, parent) {
    if (child instanceof _prosemirrorModel.Node) {
      child.marks.forEach(function (mark, index) {
        if (!mark.attrs[ATTR_OVERRIDDEN]) {
          tasks.push({
            child,
            pos,
            mark
          });
        }
      });
    }
  });
  return handleRemoveMarks(tr, tasks, from, to, schema);
}

function applyStyleEx(style, styleName, state, tr, node, startPos, endPos) {
  const loading = !style;

  if (loading) {
    style = (0, _customStyle.getCustomStyleByName)(styleName);
  }

  const _commands = getCustomStyleCommands(style);

  if (loading) {
    tr = onLoadRemoveAllMarksExceptOverridden(node, state.schema, startPos, endPos, tr);
  } else {
    // [FS] IRAD-1087 2020-11-02
    // Issue fix: applied link is missing after applying a custom style.
    tr = removeAllMarksExceptLink(startPos, endPos, tr, state.schema);
  }

  const newattrs = Object.assign({}, node.attrs); // [FS] IRAD-1074 2020-10-22
  // Issue fix on not removing center alignment when switch style with center
  // alignment to style with left alignment

  newattrs['align'] = null;
  newattrs['lineSpacing'] = null;
  newattrs['paragraphSpacingAfter'] = null;
  newattrs['paragraphSpacingBefore'] = null;

  _commands.forEach(element => {
    // to set the node attribute for text-align
    if (element instanceof _TextAlignCommand.default) {
      newattrs['align'] = style.align; // to set the node attribute for line-height
    } else if (element instanceof _TextLineSpacingCommand.default) {
      // [FS] IRAD-1104 2020-11-13
      // Issue fix : Linespacing Double and Single not applied in the sample text paragrapgh
      newattrs['lineSpacing'] = (0, _toCSSLineSpacing.getLineSpacingValue)(style.lineheight);
    } else if (element instanceof _ParagraphSpacingCommand.default) {
      // [FS] IRAD-1100 2020-11-05
      // Add in leading and trailing spacing (before and after a paragraph)
      newattrs['paragraphSpacingAfter'] = style.spaceafter ? style.spaceafter : null;
      newattrs['paragraphSpacingBefore'] = style.spacebefore ? style.spacebefore : null;
    } else if (element instanceof _IndentCommand.default) {
      newattrs['indent'] = style.indent;
    } else if (element instanceof _ListToggleCommand.default) {
      newattrs['indent'] = 0;
    } // to set the marks for the node


    if (element.executeCustom) {
      tr = element.executeCustom(state, tr, startPos, endPos);
    }
  }); // to set custom styleName attribute for node


  newattrs['styleName'] = styleName;
  tr = _setNodeAttribute(node, tr, startPos, endPos, newattrs);
  return tr;
} // Need to change this function code duplicates with applyStyle()


function applyLatestStyle(styleName, state, tr, node, startPos, endPos) {
  return applyStyleEx(null, styleName, state, tr, node, startPos, endPos);
}

function isAllowedNode(node) {
  return node.type.name === 'paragraph';
} // [FS] IRAD-1088 2020-10-05
// set custom style for node


function _setNodeAttribute(node, tr, from, to, attribute) {
  // Verify the parent node type.
  if (isAllowedNode(node)) {
    node.descendants(function (child, pos, parent) {
      tr = tr.setNodeMarkup(from, undefined, attribute);
    });
  }

  return tr;
} // [FS] IRAD-1087 2020-11-02
// Issue fix: Missing the applied link after applying a style


function removeAllMarksExceptLink(from, to, tr, schema) {
  const {
    doc
  } = tr;
  const tasks = [];
  doc.nodesBetween(from, to, (node, pos) => {
    if (node.marks && node.marks.length) {
      node.marks.some(mark => {
        if ('link' !== mark.type.name) {
          tasks.push({
            node,
            pos,
            mark
          });
        }
      });
      return true;
    }

    return true;
  });
  return handleRemoveMarks(tr, tasks, from, to, schema);
}

function handleRemoveMarks(tr, tasks, from, to, schema) {
  tasks.forEach(job => {
    const {
      mark
    } = job;
    tr = tr.removeMark(from, to, mark.type);
  });
  tr = (0, _TextAlignCommand.setTextAlign)(tr, schema, null);
  return tr;
} // [FS] IRAD-1087 2020-10-14
// Apply selected styles to document


function applyStyle(style, styleName, state, tr) {
  const {
    selection
  } = state;
  const startPos = selection.$from.before(1);
  const endPos = selection.$to.after(1);
  const node = getNode(state, startPos, endPos);
  return applyStyleEx(style, styleName, state, tr, node, startPos, endPos);
} //to get the selected node


function getNode(state, from, to) {
  let selectedNode = null;
  state.doc.nodesBetween(from, to, (node, startPos) => {
    if (node.type.name === 'paragraph') {
      selectedNode = node;
    }
  });
  return selectedNode;
}

var _default = CustomStyleCommand;
exports.default = _default;