package data;

import java.util.*;

/**
  * StockFromValueCreator that tries to fill a Stock using only items from another Stock.
  *
  * @author Steffen Zschaler
  * @version 2.0 18/08/1999
  * @since v0.5
  */
public class StockFromStockCreator extends Object implements StockFromValueCreator {

  /**
    * The CatalogItemValue used to determine the CatalogItems' values.
    */
  protected CatalogItemValue m_civEvaluator;

  /**
    * The source Stock.
    */
  protected Stock m_stSource;

  /**
    * Create a new StockFromStockCreator.
    *
    * @param stSource the source Stock.
    * @param civ the CatalogItemValue used to determine the CatalogItems' values.
    */
  public StockFromStockCreator (Stock stSource,
                                CatalogItemValue civ) {
    super();

    m_stSource = stSource;
    m_civEvaluator = civ;
  }

  /**
    * Try to fill the given Stock using only items from the source Stock.
    *
    * <p>As this algorithm does not use backtracking, it may not always find a solution even if one would be
    * possible.</p>
    *
    * <p><strong>Attention</strong>: The items that are added to the destination Stock will be removed from the
    * source Stock.</p>
    *
    * @override Never
    */
  public Value fillStock (Stock st, Value v, DataBasket db) {
    Catalog c = st.getCatalog (db);

    if (c != m_stSource.getCatalog (db)) {
      throw new CatalogConflictException();
    }

    List lCI = new LinkedList();                    // get the catalog's items
    for (Iterator i = c.iterator (db, false); i.hasNext();) {
      lCI.add (i.next());
    }

    if (lCI.size() == 0) {
      return v;
    }

    Collections.sort (lCI,                          // Sort the items, greates first
                      DefaultCountingStockFromValueCreator.invertedCIValueOrder (m_civEvaluator));


    // building the Stock
    for (Iterator i = lCI.iterator(); i.hasNext();) {

      CatalogItem ci = (CatalogItem) i.next();
      Value vItemValue = m_civEvaluator.getValue (ci);

      for (Iterator j = m_stSource.get (ci.getName(), db, false); j.hasNext();) {
        if (vItemValue.compareTo (v) <= 0) {
          StockItem si = (StockItem) j.next();

          try {
            j.remove();

            st.add (si, db);

            v.subtractAccumulating (vItemValue);
          }
          catch (UnsupportedOperationException uoe) {}
        }
      }
    }

    return v;
  }
}