export function fromTemplateOnAtom()

in packages/ketcher-core/src/application/editor/actions/template.ts [92:208]


export function fromTemplateOnAtom(
  restruct,
  template,
  aid,
  angle,
  extraBond,
  isPreview = false,
): [Action, { atoms: number[]; bonds: number[] }] {
  let action = new Action();

  const tmpl = template.molecule;
  const struct = restruct.molecule;

  const isTmplSingleGroup = template.molecule.isSingleGroup();

  let atom = struct.atoms.get(aid); // aid - the atom that was clicked on
  let aid1 = aid; // aid1 - the atom on the other end of the extra bond || aid

  let delta: any = null;

  if (extraBond) {
    // create extra bond after click on atom
    const extraRes = extraBondAction(restruct, aid, angle);
    action = extraRes.action;
    aid1 = extraRes.aid1;

    atom = struct.atoms.get(aid1);
    delta =
      utils.calcAngle(struct.atoms.get(aid).pp, atom.pp) - template.angle0;
  } else {
    if (angle === null) {
      angle = utils.calcAngle(atom.pp, atomForNewBond(restruct, aid).pos);
    }
    delta = angle - template.angle0;
  }

  const map = new Map();
  const xy0 = tmpl.atoms.get(template.aid).pp;
  const frid = atomGetAttr(restruct, aid, 'fragment');

  /* For merge */
  const pasteItems = {
    // only atoms and bonds now
    atoms: [] as number[],
    bonds: [] as number[],
  };
  /* ----- */

  tmpl.atoms.forEach((a, id) => {
    const attrs: any = Atom.getAttrHash(a);
    attrs.fragment = frid;

    if (id === template.aid) {
      action.mergeWith(fromAtomsAttrs(restruct, aid1, attrs, true));
      map.set(id, aid1);
      pasteItems.atoms.push(aid1);
    } else {
      const v = Vec2.diff(a.pp, xy0).rotate(delta).add(atom.pp);

      const operation = new AtomAdd(attrs, v.get_xy0()).perform(
        restruct,
      ) as AtomAdd;
      action.addOp(operation);
      map.set(id, operation.data.aid);
      pasteItems.atoms.push(operation.data.aid);
    }
  });

  if (!isTmplSingleGroup) mergeSgroups(action, restruct, pasteItems.atoms, aid);

  tmpl.bonds.forEach((bond) => {
    const operation = new BondAdd(
      map.get(bond.begin),
      map.get(bond.end),
      bond,
    ).perform(restruct) as BondAdd;
    action.addOp(operation);
    new BondAttr(operation.data.bid, 'isPreview', isPreview).perform(restruct);

    pasteItems.bonds.push(operation.data.bid);
  });

  tmpl.sgroups.forEach((sg: SGroup) => {
    const newsgid = restruct.molecule.sgroups.newId();
    const sgAtoms = sg.atoms.map((aid) => map.get(aid));
    const attachmentPoints = sg.cloneAttachmentPoints(map);
    const sgAction = fromSgroupAddition(
      restruct,
      sg.type,
      sgAtoms,
      {
        ...sg.data,
        expanded: isPreview ? true : sg.data.expanded,
      },
      newsgid,
      attachmentPoints,
      atom.pp,
      sg.type === 'SUP' ? sg.isExpanded() : null,
      sg.data.name,
    );
    sgAction.operations.reverse().forEach((oper) => {
      action.addOp(oper);
    });
  });

  action.operations.reverse();

  action.addOp(new CalcImplicitH([...pasteItems.atoms, aid]).perform(restruct));
  action.mergeWith(
    fromBondStereoUpdate(
      restruct,
      restruct.molecule.bonds.get(pasteItems.bonds[0]),
    ),
  );

  return [action, pasteItems];
}