# AudioBook.java

    package com.university.bookstore.model;

    /**
     * Represents an audio book that implements both Material and Media interfaces.
     * Demonstrates multiple inheritance through interfaces.
     *
     * @author Navid Mohaghegh
     * @version 2.0
     * @since 2024-09-15
     */
    public class AudioBook extends Material implements Media {

        private final String isbn;
        private final String author;
        private final String narrator;
        private final int duration;
        private final String format;
        private final double fileSize;
        private final boolean streamingOnly;
        private final MediaQuality quality;
        private final String language;
        private final boolean unabridged;

        /**
         * Creates a new AudioBook with full specifications.
         *
         * @param isbn ISBN identifier
         * @param title book title
         * @param author original author
         * @param narrator voice narrator
         * @param price price in dollars
         * @param year publication year
         * @param duration duration in minutes
         * @param format audio format (MP3, M4B, etc.)
         * @param fileSize size in megabytes
         * @param quality audio quality level
         * @param language narration language
         * @param unabridged true if unabridged version
         */
        public AudioBook(String isbn, String title, String author, String narrator,
                         double price, int year, int duration, String format,
                         double fileSize, MediaQuality quality, String language,
                         boolean unabridged) {
            super(validateIsbn(isbn), title, price, year, MaterialType.AUDIO_BOOK);
            this.isbn = this.id;
            this.author = validateStringField(author, "Author");
            this.narrator = validateStringField(narrator, "Narrator");
            this.duration = validateDuration(duration);
            this.format = validateStringField(format, "Format");
            this.fileSize = validateFileSize(fileSize);
            this.streamingOnly = false;
            this.quality = quality != null ? quality : MediaQuality.STANDARD;
            this.language = validateStringField(language, "Language");
            this.unabridged = unabridged;
        }

        private static String validateIsbn(String isbn) {
            if (isbn == null) {
                throw new NullPointerException("ISBN cannot be null");
            }
            String cleaned = isbn.replaceAll("-", "").trim();
            if (cleaned.length() < 10 || cleaned.length() > 13) {
                throw new IllegalArgumentException("Invalid ISBN: " + isbn);
            }
            return cleaned;
        }

        private int validateDuration(int duration) {
            if (duration <= 0) {
                throw new IllegalArgumentException(
                    "Duration must be positive. Provided: " + duration);
            }
            return duration;
        }

        private double validateFileSize(double fileSize) {
            if (fileSize <= 0) {
                throw new IllegalArgumentException(
                    "File size must be positive. Provided: " + fileSize);
            }
            return fileSize;
        }

        @Override
        public String getCreator() {
            return author + " (Narrated by " + narrator + ")";
        }

        @Override
        public String getDisplayInfo() {
            return String.format("%s by %s, narrated by %s - %s, %d hours %d minutes, $%.2f",
                title, author, narrator,
                unabridged ? "Unabridged" : "Abridged",
                duration / 60, duration % 60, price);
        }

        @Override
        public int getDuration() {
            return duration;
        }

        @Override
        public String getFormat() {
            return format;
        }

        @Override
        public double getFileSize() {
            return fileSize;
        }

        @Override
        public boolean isStreamingOnly() {
            return streamingOnly;
        }

        @Override
        public MediaQuality getQuality() {
            return quality;
        }

        @Override
        public double getDiscountRate() {
            if (!unabridged) {
                return 0.10;
            }
            return 0.0;
        }

        /**
         * Calculates listening sessions based on daily listening time.
         *
         * @param minutesPerDay daily listening time
         * @return number of days to complete
         */
        public int calculateListeningSessions(int minutesPerDay) {
            if (minutesPerDay <= 0) {
                return 0;
            }
            return (int) Math.ceil((double) duration / minutesPerDay);
        }

        /**
         * Gets playback speed adjusted duration.
         *
         * @param speed playback speed (1.0 = normal, 1.5 = 1.5x, etc.)
         * @return adjusted duration in minutes
         */
        public int getAdjustedDuration(double speed) {
            if (speed <= 0) {
                throw new IllegalArgumentException("Speed must be positive");
            }
            return (int) Math.ceil(duration / speed);
        }

        /** Gets the ISBN. @return the ISBN */
        public String getIsbn() {
            return isbn;
        }

        /** Gets the author. @return the author */
        public String getAuthor() {
            return author;
        }

        /** Gets the narrator. @return the narrator */
        public String getNarrator() {
            return narrator;
        }

        /** Gets the language. @return the language */
        public String getLanguage() {
            return language;
        }

        /** Checks if unabridged. @return true if unabridged */
        public boolean isUnabridged() {
            return unabridged;
        }

        @Override
        public String toString() {
            return String.format("AudioBook[ISBN=%s, Title='%s', Author='%s', Narrator='%s', Duration=%dmin, Format=%s, %s, Price=$%.2f]",
                isbn, title, author, narrator, duration, format,
                unabridged ? "Unabridged" : "Abridged", price);
        }
    }