/**
   * Get the container which the bond is found on resonance from a IMolecule. It is based on looking
   * if the order of the bond changes. Return null is any is found.
   *
   * @param molecule The IMolecule to analyze
   * @param bond The IBond
   * @return The container with the bond
   */
  @TestMethod("testGetContainer_IMolecule_IBond")
  public IAtomContainer getContainer(IMolecule molecule, IBond bond) {
    IAtomContainerSet setOfCont = getContainers(molecule);
    if (setOfCont == null) return null;

    for (IAtomContainer container : setOfCont.atomContainers()) {
      if (container.contains(bond)) return container;
    }

    return null;
  }
  /**
   * Search if the setOfAtomContainer contains the atomContainer
   *
   * @param set ISetOfAtomContainer object where to search
   * @param atomContainer IAtomContainer to search
   * @return True, if the atomContainer is contained
   */
  private boolean existAC(IAtomContainerSet set, IAtomContainer atomContainer) {

    IAtomContainer acClone = null;
    try {
      acClone = (IMolecule) atomContainer.clone();
      if (!lookingSymmetry) {
        /*remove all aromatic flags*/
        for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false);
        for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false);
      }
    } catch (CloneNotSupportedException e1) {
      e1.printStackTrace();
    }

    for (int i = 0; i < acClone.getAtomCount(); i++)
      //			if(acClone.getAtom(i).getID() == null)
      acClone.getAtom(i).setID("" + acClone.getAtomNumber(acClone.getAtom(i)));

    if (lookingSymmetry) {
      try {
        CDKHueckelAromaticityDetector.detectAromaticity(acClone);
      } catch (CDKException e) {
        e.printStackTrace();
      }
    } else {
      if (!lookingSymmetry) {
        /*remove all aromatic flags*/
        for (IAtom atom : acClone.atoms()) atom.setFlag(CDKConstants.ISAROMATIC, false);
        for (IBond bond : acClone.bonds()) bond.setFlag(CDKConstants.ISAROMATIC, false);
      }
    }
    for (int i = 0; i < set.getAtomContainerCount(); i++) {
      IAtomContainer ss = set.getAtomContainer(i);
      for (int j = 0; j < ss.getAtomCount(); j++)
        //				if(ss.getAtom(j).getID() == null)
        ss.getAtom(j).setID("" + ss.getAtomNumber(ss.getAtom(j)));

      try {

        if (!lookingSymmetry) {
          QueryAtomContainer qAC =
              QueryAtomContainerCreator.createSymbolChargeIDQueryContainer(acClone);
          if (UniversalIsomorphismTester.isIsomorph(ss, qAC)) {
            QueryAtomContainer qAC2 =
                QueryAtomContainerCreator.createSymbolAndBondOrderQueryContainer(acClone);
            if (UniversalIsomorphismTester.isIsomorph(ss, qAC2)) return true;
          }
        } else {
          QueryAtomContainer qAC =
              QueryAtomContainerCreator.createSymbolAndChargeQueryContainer(acClone);
          CDKHueckelAromaticityDetector.detectAromaticity(ss);
          if (UniversalIsomorphismTester.isIsomorph(ss, qAC)) return true;
        }

      } catch (CDKException e1) {
        System.err.println(e1);
        logger.error(e1.getMessage());
        logger.debug(e1);
      }
    }
    return false;
  }
  /**
   * Get the container which is found resonance from a IMolecule. It is based on looking if the
   * order of the bond changes.
   *
   * @param molecule The IMolecule to analyze
   * @return The different containers
   */
  @TestMethod("testGetContainers_IMolecule")
  public IAtomContainerSet getContainers(IMolecule molecule) {
    IAtomContainerSet setOfCont = molecule.getBuilder().newAtomContainerSet();
    IMoleculeSet setOfMol = getStructures(molecule);

    if (setOfMol.getMoleculeCount() == 0) return setOfCont;

    /*extraction of all bonds which has been produced a changes of order*/
    List<IBond> bondList = new ArrayList<IBond>();
    for (int i = 1; i < setOfMol.getMoleculeCount(); i++) {
      IMolecule mol = setOfMol.getMolecule(i);
      for (int j = 0; j < mol.getBondCount(); j++) {
        IBond bond = molecule.getBond(j);
        if (!mol.getBond(j).getOrder().equals(bond.getOrder())) {
          if (!bondList.contains(bond)) bondList.add(bond);
        }
      }
    }

    if (bondList.size() == 0) return null;

    int[] flagBelonging = new int[bondList.size()];
    for (int i = 0; i < flagBelonging.length; i++) flagBelonging[i] = 0;
    int[] position = new int[bondList.size()];
    int maxGroup = 1;

    /*Analysis if the bond are linked together*/
    List<IBond> newBondList = new ArrayList<IBond>();
    newBondList.add(bondList.get(0));

    int pos = 0;
    for (int i = 0; i < newBondList.size(); i++) {

      if (i == 0) flagBelonging[i] = maxGroup;
      else {
        if (flagBelonging[position[i]] == 0) {
          maxGroup++;
          flagBelonging[position[i]] = maxGroup;
        }
      }

      IBond bondA = newBondList.get(i);
      for (int ato = 0; ato < 2; ato++) {
        IAtom atomA1 = bondA.getAtom(ato);
        List<IBond> bondA1s = molecule.getConnectedBondsList(atomA1);
        for (int j = 0; j < bondA1s.size(); j++) {
          IBond bondB = bondA1s.get(j);
          if (!newBondList.contains(bondB))
            for (int k = 0; k < bondList.size(); k++)
              if (bondList.get(k).equals(bondB))
                if (flagBelonging[k] == 0) {
                  flagBelonging[k] = maxGroup;
                  pos++;
                  newBondList.add(bondB);
                  position[pos] = k;
                }
        }
      }
      // if it is final size and not all are added
      if (newBondList.size() - 1 == i)
        for (int k = 0; k < bondList.size(); k++)
          if (!newBondList.contains(bondList.get(k))) {
            newBondList.add(bondList.get(k));
            position[i + 1] = k;
            break;
          }
    }
    /*creating containers according groups*/
    for (int i = 0; i < maxGroup; i++) {
      IAtomContainer container = molecule.getBuilder().newAtomContainer();
      for (int j = 0; j < bondList.size(); j++) {
        if (flagBelonging[j] != i + 1) continue;
        IBond bond = bondList.get(j);
        IAtom atomA1 = bond.getAtom(0);
        IAtom atomA2 = bond.getAtom(1);
        if (!container.contains(atomA1)) container.addAtom(atomA1);
        if (!container.contains(atomA2)) container.addAtom(atomA2);
        container.addBond(bond);
      }
      setOfCont.addAtomContainer(container);
    }
    return setOfCont;
  }