/**
  * The number of seats in the requested level that are neither held nor reserved
  *
  * @param venueLevel a numeric venue level identifier to limit the search
  * @return the number of tickets available on the provided level
  */
 @Override
 public int numSeatsAvailable(Integer venueLevel) {
   resetHolds();
   List<LevelVO> levelList = TemporaryDatabase.getStage();
   int seatsAvailable = 0;
   if (levelList != null && !levelList.isEmpty()) {
     for (LevelVO levelVO : levelList) {
       if (levelVO != null && levelVO.getLevelId() == venueLevel) {
         Map<Integer, List<SeatVO>> rowsAndSeats = levelVO.getRowsAndSeats();
         if (rowsAndSeats != null && !rowsAndSeats.isEmpty()) {
           Set<Integer> rows = rowsAndSeats.keySet();
           if (rows != null && !rows.isEmpty()) {
             for (Integer rowId : rows) {
               if (rowId != -1) {
                 List<SeatVO> seats = rowsAndSeats.get(rowId);
                 if (seats != null && !seats.isEmpty()) {
                   for (SeatVO seatVO : seats) {
                     if (seatVO.getStatusCode() == Constants.SEAT_AVAILABLE) {
                       seatsAvailable++;
                     }
                   }
                 }
               }
             }
           }
         }
       }
     }
   }
   return seatsAvailable;
 }
 /**
  * If holds are not expired, seat status will be changed to reserved.
  *
  * @param levelNumber The level number where seats need to be reserved
  * @param rowNumber row number where seats need to be reserved
  * @param seatNum seat number to be reserved
  * @return reservation status.
  */
 private boolean processSeatReserve(int levelNumber, int rowNumber, int seatNum) {
   List<LevelVO> levels = TemporaryDatabase.getStage();
   for (LevelVO levelVO : levels) {
     if (levelVO != null && levelVO.getLevelId() == levelNumber) {
       Map<Integer, List<SeatVO>> rowsAndSeats = levelVO.getRowsAndSeats();
       Set<Integer> rows = rowsAndSeats.keySet();
       if (rows != null && !rows.isEmpty()) {
         for (Integer row : rows) {
           if (row == rowNumber) {
             List<SeatVO> seats = rowsAndSeats.get(row);
             if (seats != null && !seats.isEmpty()) {
               for (SeatVO seatVO : seats) {
                 if (seatVO != null
                     && seatVO.getSeatNum() == seatNum
                     && seatVO.getStatusCode() == Constants.SEAT_HOLD) {
                   // Update stauts code
                   if (holdNotExpired(seatVO.getHoldTimeStamp().getTime())) {
                     seatVO.setStatusCode(Constants.SEAT_RESERVED);
                     return true;
                   } else {
                     seatVO.setStatusCode(Constants.SEAT_AVAILABLE);
                     return false;
                   }
                 }
               }
             }
           }
         }
       }
     }
   }
   return false;
 }
  /**
   * @param minLevel minimum level where best selection starts
   * @param maxLevel maximum level where best selection ends
   * @param numSeats number of seats need to be put on hold
   * @param seatsToHold List keeps track of seats on hold in this perticualr request.
   * @return SeatHold object which contains hold details.
   */
  private SeatHoldVO processSeatHold(
      int minLevel, int maxLevel, int numSeats, List<SeatHoldVO> seatsToHold) {
    List<LevelVO> levels = TemporaryDatabase.getStage();
    if (numSeats > 0) {
      // Generates a randome SeatHoldId while creating SeatHold object.
      SeatHoldVO seatHold = new SeatHoldVO(generateRandom());
      for (LevelVO levelVO : levels) {
        if (numSeats <= 0) {
          break;
        }
        if (levelVO != null && levelVO.getLevelId() == minLevel && minLevel <= maxLevel) {
          Map<Integer, List<SeatVO>> rowsAndSeats = levelVO.getRowsAndSeats();
          Set<Integer> rows = rowsAndSeats.keySet();
          if (rows != null && !rows.isEmpty()) {
            for (Integer row : rows) {
              if (numSeats <= 0) {
                break;
              }
              List<SeatVO> seats = rowsAndSeats.get(row);
              if (seats != null && !seats.isEmpty()) {
                for (SeatVO seatVO : seats) {
                  if (numSeats <= 0) {
                    break;
                  }
                  if (seatVO != null
                      && seatVO.getStatusCode() == Constants.SEAT_AVAILABLE
                      && numSeats > 0) {
                    Date dt = new Date();
                    // Update with Random ID
                    SeatInfoVO seatInfo =
                        new SeatInfoVO(
                            levelVO.getLevelId(),
                            row,
                            seatVO.getSeatNum(),
                            levelVO.getPrice(),
                            levelVO.getLevelName(),
                            dt);
                    seatHold.addSeat(seatInfo);

                    // Update stauts code
                    seatVO.setHoldTimeStamp(dt);
                    seatVO.setStatusCode(Constants.SEAT_HOLD);
                    numSeats--;
                  }
                }
              }
            }
          }
          minLevel++;
        }
      }
      seatsToHold.add(seatHold);
      return seatHold;
    }
    return null;
  }
  /**
   * This method updates temporary database maps hold status to AVAILABLE, if Hold expired after 10
   * seconds.
   */
  private void resetHolds() {
    // Reset Holds on Levels
    List<LevelVO> levels = TemporaryDatabase.getStage();
    for (LevelVO levelVO : levels) {
      if (levelVO != null) {
        Map<Integer, List<SeatVO>> rowsAndSeats = levelVO.getRowsAndSeats();
        Set<Integer> rows = rowsAndSeats.keySet();
        if (rows != null && !rows.isEmpty()) {
          for (Integer row : rows) {
            List<SeatVO> seats = rowsAndSeats.get(row);
            if (seats != null && !seats.isEmpty()) {
              for (SeatVO seatVO : seats) {
                if (seatVO != null && seatVO.getStatusCode() == Constants.SEAT_HOLD) {
                  if (!holdNotExpired(seatVO.getHoldTimeStamp().getTime())) {
                    // Update stauts code to available
                    seatVO.setStatusCode(Constants.SEAT_AVAILABLE);
                  }
                }
              }
            }
          }
        }
      }
    }

    // Reset Holds on HoldsAndSeats
    Map<String, List<SeatHoldVO>> holds = TemporaryDatabase.getSeatsOnHold();
    if (holds != null && !holds.isEmpty()) {
      Collection<List<SeatHoldVO>> seatHolds = holds.values();
      if (seatHolds != null && !seatHolds.isEmpty()) {
        for (List<SeatHoldVO> seatHoldList : seatHolds) {
          if (seatHoldList != null && !seatHoldList.isEmpty()) {
            Iterator<SeatHoldVO> seatHoldIter = seatHoldList.iterator();
            while (seatHoldIter.hasNext()) {
              SeatHoldVO seatHold = seatHoldIter.next();
              if (seatHold != null
                  && seatHold.getSeatsList() != null
                  && !seatHold.getSeatsList().isEmpty()) {
                Iterator<SeatInfoVO> seatInfoIter = seatHold.getSeatsList().iterator();
                while (seatInfoIter.hasNext()) {
                  SeatInfoVO seatInfo = seatInfoIter.next();
                  if (!holdNotExpired(seatInfo.getHoldTimeStamp().getTime())) {
                    seatInfoIter.remove();
                  }
                }
              }

              if (seatHold != null && seatHold.getSeatsList().isEmpty()) {
                seatHoldIter.remove();
              }
            }
          }
        }
      }
    }

    //        Map<String, List<SeatHoldVO>> resetHolds = TemporaryDatabase.getSeatsOnHold();
    //        if (resetHolds != null && !resetHolds.isEmpty()) {
    //            Collection<List<SeatHoldVO>> seatHolds = resetHolds.values();
    //            Iterator<List<SeatHoldVO>> seatIter = seatHolds.iterator();
    //            while (seatIter.hasNext()) {
    //                List<SeatHoldVO> seatholdList = seatIter.next();
    //                if (seatholdList != null && !seatholdList.isEmpty()) {
    //                    Iterator<SeatHoldVO> seatholdIter = seatholdList.iterator();
    //                    while (seatholdIter.hasNext()) {
    //
    //                    }
    //                }
    //            }
    //        }

  }