/* Copyright (c) 2005 Stanford University and Christopher Bruns
 * 
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including 
 * without limitation the rights to use, copy, modify, merge, publish, 
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject
 * to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

/*
 * Created on Nov 3, 2005
 * Original author: Christopher Bruns
 */
package org.simtk.isimsu;

import java.util.*;

/** 
 *  
  * @author Christopher Bruns
  * 
  * Represents set of dissolved ions in a simulation
 */
public class SaltCondition 
extends Vector<IonConcentration> 
implements List<IonConcentration>, Comparable<SaltCondition>
{
    // private Collection ionConcentrations = new Vector();
    private SaltConditionRange parent;
    private String conditionName;
    
    public SaltCondition(SaltConditionRange parent) {
        this.parent = parent;
    }
    
    // Need to sort conditions for excess potential file
    public int compareTo(SaltCondition otherCondition) {
        final int BEFORE = -1;
        final int EQUAL = 0;
        final int AFTER = 1;

        if (this == otherCondition) return EQUAL;
        
        // Sort the ions in each set
        List<IonConcentration> sortedConcentrations1 = 
            new Vector<IonConcentration>(this);
        List<IonConcentration> sortedConcentrations2 = 
            new Vector<IonConcentration>(otherCondition);
        Collections.sort(sortedConcentrations1);
        Collections.sort(sortedConcentrations2);

        // Make sure the sets of ions are the same
        if (sortedConcentrations1.size() != sortedConcentrations2.size())
            throw new RuntimeException("Ion sets don't match (different numbers)");
        for (int i = 0; i < sortedConcentrations1.size(); ++i) {

            // Make sure both conditions contain the same ions
            if ( !(sortedConcentrations1.get(i).getIonSpecies().equals(sortedConcentrations2.get(i).getIonSpecies())) ) {
                throw new RuntimeException("Ion sets don't match");
            }
            
            double conc1 = sortedConcentrations1.get(i).getConcentration();
            double conc2 = sortedConcentrations2.get(i).getConcentration();
            
            // Sort by increasing concentration
            if (conc1 < conc2) return BEFORE;
            if (conc1 > conc2) return AFTER;
        }
        
        assert this.equals(otherCondition) : "compareTo inconsistent with equals.";

        return EQUAL;        
    }
    
    public SaltConditionRange getParentRange() {
        return parent;
    }
    
    public String getName() {return conditionName;}
    public void setName(String conditionName) {this.conditionName = conditionName;}
    
    public int getIonCount() { return size(); }
    
    public void addIonConcentration(IonConcentration ionConcentration) {
        add(ionConcentration);
    }
    
    public float getTemperature() {return parent.getTemperature();}
    public float getSolventPermittivity() {return parent.getSolventPermittivity();}
    
    /**
     * Display set of ions in format suitable for ISIM input file IONS section
     * 
     * e.g.
     * ********************
     * MODEL                         L
     * TYPES                         2 
     * CALCIUM                       75.0    2.0  2.41  0.450 
     * CHLORINE                      150.0  -1.0  4.86  0.168
     * ********************
     * 
     * @return
     */
    public String toInputText() {
        String answer = new String("");
        
        // IonSpecies firstSpecies = getIonSpecies(0);
        // if (firstSpecies == null) return "";
        
        answer += "MODEL                         ";
        if (parent.getIonSurfaceModel() == IonSpecies.HARD_SPHERE_MODEL)
            answer += "H";
        else
            answer += "L"; // Lennard Jones
        answer += "\n";

        answer += "TYPES                         ";
        answer += size();
        answer += "\n";
        
        List<IonConcentration> sortedIons = new Vector<IonConcentration>(this);
        Collections.sort(sortedIons);
        
        for (IonConcentration ion : sortedIons) {

            // CALCIUM                       75.0    2.0  2.41  0.450 

            // TODO - figure out importance of spacing
            answer += ion.getIonId();
            answer += "  ";
            answer += ion.getConcentration();
            answer += "  ";
            answer += ion.getCharge();
            answer += "  ";
            answer += ion.getRadius();
            answer += "  ";
            answer += ion.getSurfaceWellDepth();

            answer += "\n";
        }
        
        return answer;
    }
    
    public String toString() {return getName();}
}

