# PriceSortedIterator.java

    package com.university.bookstore.iterator;

    import java.util.ArrayList;
    import java.util.Comparator;
    import java.util.List;
    import java.util.NoSuchElementException;

    import com.university.bookstore.model.Material;

    /**
     * Iterator that returns materials sorted by price.
     * Can sort in ascending or descending order.
     *
     * @author Navid Mohaghegh
     * @version 3.0
     * @since 2024-09-15
     */
    public class PriceSortedIterator implements MaterialIterator {

        private final List<Material> sortedMaterials;
        private int currentIndex;
        private final boolean ascending;

        /**
         * Creates a new price sorted iterator.
         *
         * @param materials the list of materials to iterate over
         * @param ascending true for ascending order, false for descending
         */
        public PriceSortedIterator(List<Material> materials, boolean ascending) {
            this.sortedMaterials = new ArrayList<>(materials);
            this.ascending = ascending;
            this.currentIndex = 0;

            // Sort materials by price
            Comparator<Material> priceComparator = Comparator.comparing(Material::getPrice);
            if (!ascending) {
                priceComparator = priceComparator.reversed();
            }
            this.sortedMaterials.sort(priceComparator);
        }

        @Override
        public boolean hasNext() {
            return currentIndex < sortedMaterials.size();
        }

        @Override
        public Material next() {
            if (!hasNext()) {
                throw new NoSuchElementException("No more elements");
            }
            return sortedMaterials.get(currentIndex++);
        }

        @Override
        public void reset() {
            currentIndex = 0;
        }

        @Override
        public int getCurrentPosition() {
            return currentIndex;
        }

        @Override
        public int getTotalCount() {
            return sortedMaterials.size();
        }

        @Override
        public int getRemainingCount() {
            return sortedMaterials.size() - currentIndex;
        }

        @Override
        public boolean isAtBeginning() {
            return currentIndex == 0;
        }

        @Override
        public boolean isAtEnd() {
            return currentIndex >= sortedMaterials.size();
        }

        /**
         * Gets the sort order.
         *
         * @return true if ascending, false if descending
         */
        public boolean isAscending() {
            return ascending;
        }

        /**
         * Gets the current material without advancing the iterator.
         *
         * @return the current material
         * @throws NoSuchElementException if at the end
         */
        public Material peek() {
            if (currentIndex >= sortedMaterials.size()) {
                throw new NoSuchElementException("No more elements");
            }
            return sortedMaterials.get(currentIndex);
        }

        /**
         * Gets the next material without advancing the iterator.
         *
         * @return the next material
         * @throws NoSuchElementException if no next element
         */
        public Material peekNext() {
            if (currentIndex + 1 >= sortedMaterials.size()) {
                throw new NoSuchElementException("No next element");
            }
            return sortedMaterials.get(currentIndex + 1);
        }

        @Override
        public String toString() {
            return String.format("PriceSortedIterator[Order=%s, Position=%d/%d]",
                ascending ? "ASC" : "DESC", getCurrentPosition(), getTotalCount());
        }
    }