goog.provide('jchemhub.model.Molecule');
goog.require('goog.array');
goog.require('jchemhub.ring.RingFinder');
goog.require('jchemhub.ring.SSSRFinder');

/**
 * Class representing a Molecule
 * 
 * @param {string=}
 *            opt_name, Name of molecule, defaults to empty string.
 * @constructor
 */
jchemhub.model.Molecule = function(opt_name) {
	/**
	 * bonds belonging to this molecule
	 * 
	 * @type {Array.<jchemhub.model.Bond>}
	 * 
	 */
	this.bonds = [];

	/**
	 * atoms belonging to this molecule
	 * 
	 * @type {Array.<jchemhub.model.Atom>}
	 */
	this.atoms = [];

	/**
	 * name of molecule
	 * 
	 * @type {string}
	 */
	this.name = opt_name ? opt_name : "";
	
	/**
	 * SSSR calculated for this molecule
	 */
	this.sssr=[];
	this.mustRecalcSSSR=true;

};

/**
 * Add a bond to molecule.
 * 
 * @param {jchemhub.model.Bond}
 *            bond The bond to add.
 */

jchemhub.model.Molecule.prototype.addBond = function(bond) {
	this.bonds.push(bond);
	bond.source.bonds.add(bond);
	bond.target.bonds.add(bond);
	bond.molecule = this;
};

/**
 * Get the atom of given id.
 * 
 * @param {number}
 *            id The atom id.
 * @return {jchemhub.model.Atom}
 */

jchemhub.model.Molecule.prototype.getAtom = function(id) {
	return this.atoms[id];
};

/**
 * Get the bond of given id.
 * 
 * @param {number}
 *            id The bond id.
 * @return {jchemhub.model.Bond}
 */

jchemhub.model.Molecule.prototype.getBond = function(id) {
	return this.bonds[id];
};

/**
 * Find the bond between two given atoms if it exists. Otherwise return null.
 * 
 * @param {Object}
 *            atom1
 * @param {Object}
 *            atom2
 * @return{jchemhub.model.Bond}
 */
jchemhub.model.Molecule.prototype.findBond = function(atom1, atom2) {
	for ( var i = 0, il = this.bonds.length; i < il; i++) {
		var bond = this.bonds[i];
		if ((atom1 == bond.source && atom2 == bond.target)
				|| (atom2 == bond.source && atom1 == bond.target))
			return bond;
	}
	return null;
};

/**
 * Return id of given atom. If not found, return -1;
 * 
 * @param {jchemhub.model.Atom}
 *            atom The atom to lookup.
 * @return{jchemhub.model.number}
 */
jchemhub.model.Molecule.prototype.indexOfAtom = function(atom) {
	return goog.array.indexOf(this.atoms, atom);
};

/**
 * Return id of given bond. If not found, return -1;
 * 
 * @param {jchemhub.model.Bond}
 *            bond The bond to lookup.
 * @return{jchemhub.model.number}
 */
jchemhub.model.Molecule.prototype.indexOfBond = function(bond) {
	return goog.array.indexOf(this.bonds, bond);
};

/**
 * Remove a atom from molecule.
 * 
 * @param {number|jchemhub.model.Atom}
 *            Instance or id of the atom to remove.
 */

jchemhub.model.Molecule.prototype.removeAtom = function(atomOrId) {
	var atom;
	if (atomOrId.constructor == Number) {
		atom = this.atoms[atomOrId];
	} else if (atomOrId.constructor == jchemhub.model.Atom) {
		atom = atomOrId;
	}
	var neighborBonds = atom.bonds.getValues();
	var molBonds = this.bonds; // for bond reference in anonymous method
	goog.array.forEach(neighborBonds, function(element, index, array) {
		goog.array.remove(molBonds, element);
	});
	atom.bonds.clear();
	goog.array.remove(this.atoms, atom);
	atom.molecule = undefined;

};

/**
 * Remove a bond from molecule.
 * 
 * @param {number|jchemhub.model.Bond}
 *            Instance or id of the bond to remove.
 */

jchemhub.model.Molecule.prototype.removeBond = function(bondOrId) {
	var bond;
	if (bondOrId.constructor == Number) {
		bond = this.bonds[bondOrId];
	} else {
		bond = bondOrId;
	}
	bond.source.bonds.remove(bond);
	bond.target.bonds.remove(bond);
	if(bond.source.bonds.length==0){
		goog.array.remove(this.atoms, bond.source);
		bond.source.molecule = undefined;
	}
	if(bond.target.bonds.length==0){
		goog.array.remove(this.atoms, bond.target);
		bond.target.molecule = undefined;
	
	}
	goog.array.remove(this.bonds, bond);
	bond.molecule = undefined;
	bond.source = undefined;
	bond.target = undefined;
};

/**
 * Count atoms.
 * 
 * @return{number}
 */
jchemhub.model.Molecule.prototype.countAtoms = function() {
	return this.atoms.length;
};

/**
 * Count bonds.
 */
jchemhub.model.Molecule.prototype.countBonds = function() {
	return this.bonds.length;
};

/**
 * Add an atom to molecule.
 * 
 * @param {jchemhub.model.Atom}
 *            atom The atom to add.
 */
jchemhub.model.Molecule.prototype.addAtom = function(atom) {
	this.atoms.push(atom);
	atom.molecule = this;
};



/**
 * Get rings found in this molecule
 * 
 * @return{Array.<jchemhub.ring.Ring>}
 */
jchemhub.model.Molecule.prototype.getRings = function(){

    if (this.mustRecalcSSSR) {
		  this.mustRecalcSSSR=false;
          this.sssr = jchemhub.ring.findSSSR(this);
	}
	return this.sssr;
}

@@ -1737,15 +1737,17 @@
 ) %7B%0A
-%09
+    
 for (
- 
 var 
@@ -1757,17 +1757,18 @@
  0, 
-i
 l
+i
  = 
-this
+atom1
 .bon
@@ -1786,10 +1786,10 @@
 i %3C 
-i
 l
+i
 ; i+
@@ -1793,18 +1793,24 @@
  i++) %7B%0A
-%09%09
+        
 var bond
@@ -1808,28 +1808,29 @@
  var bond = 
-this
+atom1
 .bonds%5Bi%5D;%0A%09
@@ -1832,136 +1832,102 @@
 i%5D;%0A
-%09%09if ((atom1 == bond.source && atom2 == bond.target)%0A%09%09%09%09%7C%7C (atom2 == bond.source && 
+        if (bond.getOtherAtom(
 atom1
+)
  == 
-bond.target))%0A%09%09%09return bond;%0A%09%7D%0A%09
+atom2) %7B%0A            return bond;%0A        %7D%0A    %7D%0A    
 retu

Change Molecule.findBond implementation to make use of the bonds stored in atoms. For structure 11 (mol_demo), this reduces the time needed for the SSSR calculation from 40s to 11s here.