# MaterialTypeIterator.java

    package com.university.bookstore.iterator;

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

    import com.university.bookstore.model.Material;

    /**
     * Iterator that filters materials by type.
     * Only returns materials of the specified type.
     *
     * @author Navid Mohaghegh
     * @version 3.0
     * @since 2024-09-15
     */
    public class MaterialTypeIterator implements MaterialIterator {

        private final List<Material> materials;
        private final Material.MaterialType targetType;
        private int currentIndex;
        private final int totalCount;

        /**
         * Creates a new material type iterator.
         *
         * @param materials the list of materials to iterate over
         * @param targetType the type of materials to filter for
         */
        public MaterialTypeIterator(List<Material> materials, Material.MaterialType targetType) {
            this.materials = new ArrayList<>(materials);
            this.targetType = targetType;
            this.currentIndex = 0;
            this.totalCount = (int) materials.stream()
                .filter(m -> m.getType() == targetType)
                .count();
            advanceToNext();
        }

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

        @Override
        public Material next() {
            if (!hasNext()) {
                throw new NoSuchElementException("No more elements");
            }

            Material current = materials.get(currentIndex);
            currentIndex++;
            advanceToNext();
            return current;
        }

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

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

        @Override
        public int getTotalCount() {
            return totalCount;
        }

        @Override
        public int getRemainingCount() {
            return totalCount - getCurrentPosition();
        }

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

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

        /**
         * Gets the target type this iterator filters for.
         *
         * @return the target material type
         */
        public Material.MaterialType getTargetType() {
            return targetType;
        }

        /**
         * Advances to the next material of the target type.
         */
        private void advanceToNext() {
            while (currentIndex < materials.size() &&
                   materials.get(currentIndex).getType() != targetType) {
                currentIndex++;
            }
        }

        @Override
        public String toString() {
            return String.format("MaterialTypeIterator[Type=%s, Position=%d/%d]",
                targetType, getCurrentPosition(), getTotalCount());
        }
    }