package data.stdforms.twotableformsheet;

import sale.*;

import data.*;
import data.stdforms.*;

import users.*;

/**
  * MoveStrategy for a StoringStock source and destination.
  *
  * @author Steffen Zschaler
  * @version 2.0 20/08/1999
  * @since v2.0
  */
public class SSSSStrategy extends MoveStrategy {

  /**
    * Get the sub-process that will move items from the source to the destination.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem that is selected in the source.
    * @param ttfs the FormSheet that triggers the process.
    *
    * @override Never
    */
  public Transition getMoveToDestProcess (SaleProcess p,
                                          SalesPoint sp,
                                          StoringStock ssSource,
                                          StoringStock ssDest,
                                          DataBasket db,
                                          StockItem si,
                                          TwoTableFormSheet ttfs) {
    return new GateChangeTransition (getCheckMoveToDestGate (p, sp, ssSource, ssDest, db, si, ttfs));
  }

  /**
    * Get the first gate of the sub-process that will move items from the source to the destination.
    *
    * <p>This Gate will check whether the move is allowable, and if so, will trigger a Transition that
    * performs it.</p>
    *
    * @return {@link #getCheckMoveGate}.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem that is selected in the source.
    * @param ttfs the FormSheet that triggers the process.
    *
    * @override Never Instead, override {@link #checkMove} and/or {@link #moveImpl}.
    */
  protected Gate getCheckMoveToDestGate (SaleProcess p,
                                         SalesPoint sp,
                                         StoringStock ssSource,
                                         StoringStock ssDest,
                                         DataBasket db,
                                         StockItem si,
                                         TwoTableFormSheet ttfs) {
    return getCheckMoveGate (p, sp, ssSource, ssDest, db, si, ttfs);
  }

  /**
    * Get the sub-process that will move items from the destination to the source.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem that is selected in the destination.
    * @param ttfs the FormSheet that triggers the process.
    *
    * @override Never
    */
  public Transition getMoveToSourceProcess (SaleProcess p,
                                            SalesPoint sp,
                                            StoringStock ssSource,
                                            StoringStock ssDest,
                                            DataBasket db,
                                            StockItem si,
                                            TwoTableFormSheet ttfs) {
    return new GateChangeTransition (getCheckMoveToSourceGate (p, sp, ssSource, ssDest, db, si, ttfs));
  }

  /**
    * Get the first gate of the sub-process that will move items from the destination to the source.
    *
    * <p>This Gate will check whether the move is allowable, and if so, will trigger a Transition that
    * performs it.</p>
    *
    * @return {@link #getCheckMoveGate}.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem that is selected in the destination.
    * @param ttfs the FormSheet that triggers the process.
    *
    * @override Never Instead, override {@link #checkMove} and/or {@link #moveImpl}.
    */
  protected Gate getCheckMoveToSourceGate (SaleProcess p,
                                           SalesPoint sp,
                                           StoringStock ssSource,
                                           StoringStock ssDest,
                                           DataBasket db,
                                           StockItem si,
                                           TwoTableFormSheet ttfs) {
    return getCheckMoveGate (p, sp, ssDest, ssSource, db, si, ttfs);
  }

  /**
    * Get the first gate of a sub-process that will move items from one Stock into another.
    *
    * <p>This Gate will check whether the move is allowable, and if so, will trigger a Transition that
    * performs it.</p>
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem which is to be moved from the source into the destination Stock.
    * @param ttfs the FormSheet that triggers the process.
    *
    * @override Never Instead, override {@link #checkMove} and/or {@link #moveImpl}.
    */
  protected Gate getCheckMoveGate (SaleProcess p,
                                   final SalesPoint sp,
                                   final StoringStock ssSource,
                                   final StoringStock ssDest,
                                   final DataBasket db,
                                   final StockItem si,
                                   final TwoTableFormSheet ttfs) {
    return new Gate() {
      public Transition getNextTransition (SaleProcess p, User u)
        throws InterruptedException {
        int nCheckReturn = checkMove (p, sp, ssSource, ssDest, db, si);

        if (nCheckReturn == 0) {
          return new Transition() {
            public Gate perform (SaleProcess p, User u) {
              moveImpl (p, sp, ssSource, ssDest, db, si);

              return ttfs.getGate();
            }
          };
        }
        else {
          error (p, nCheckReturn);

          return new GateChangeTransition (ttfs.getGate());
        }
      }
    };
  }

  /**
    * Check whether the indicated move is allowable. If so, return 0, otherwise return a non-zero error value
    * that can be passed on to {@link sale.stdforms.FormSheetStrategy#error}. You can assume that you are at a {@link Gate}.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem which is to be moved.
    *
    * @override Sometimes The default implementation returns 0.
    */
  protected int checkMove (SaleProcess p,
                           SalesPoint sp,
                           StoringStock ssSource,
                           StoringStock ssDest,
                           DataBasket db,
                           StockItem si)
    throws InterruptedException {
    return 0;
  }

  /**
    * Move the indicated item from the source StoringStock into the destination StoringStock. You
    * can assume that you are in a {@link Transition}.
    *
    * @param p the process into which the sub-process wil be embedded.
    * @param sp the SalesPoint, if any, at which the FormSheet is being displayed.
    * @param ssSource the source StoringStock.
    * @param ssDest the destination StoringStock.
    * @param db the DataBasket relative to which to perform the operation.
    * @param si the StockItem which is to be moved.
    *
    * @override Sometimes
    */
  protected void moveImpl (SaleProcess p,
                           SalesPoint sp,
                           StoringStock ssSource,
                           StoringStock ssDest,
                           DataBasket db,
                           StockItem si) {
    try {
      ssDest.add (ssSource.remove (si, db), db);
    }
    catch (data.events.VetoException ve) {
      error (p, REMOVE_VETO_EXCEPTION);
    }
  }
}