/**
 * 
 */
package edu.ncsu.csc216.wolf_scheduler.course;

/**
 * Creates the Course object and checks that all fields are valid.
 */
public class Course extends Activity {
    /** Min length of name field. */
    private static final int MIN_NAME_LENGTH = 5;
    /** Max length of name field. */
    private static final int MAX_NAME_LENGTH = 8;
    /** Min letter count in name */
    private static final int MIN_LETTER_COUNT = 1;
    /** Max letter count in name */
    private static final int MAX_LETTER_COUNT = 4;
    /** Number of digits in name */
    private static final int DIGIT_COUNT = 3;
    /** Length of section number */
    private static final int SECTION_LENGTH = 3;
    /** Max number of possible credits for a course */
    private static final int MAX_CREDITS = 5;
    /** Min number of possible credits for a course */
    private static final int MIN_CREDITS = 1;
    /** Course's name. */
    private String name;
    /** Course's section. */
    private String section;
    /** Course's credit hours */
    private int credits;
    /** Course's instructor */
    private String instructorId;
    /**
     * Constructs a Course object with values for all fields.
     * 
     * @param name         name of Course
     * @param title        title of Course
     * @param section      section of Course
     * @param credits      credit hours for Course
     * @param instructorId instructor's unity id
     * @param meetingDays  meeting days for Course as series of chars
     * @param startTime    start time for Course
     * @param endTime      end time for Course
     */
    public Course(String name, String title, String section, int credits, String instructorId, String meetingDays,
            int startTime, int endTime) {
        super();
		setName(name);
        setTitle(title);
        setSection(section);
        setCredits(credits);
        setInstructorId(instructorId);
        setMeetingDaysAndTime(meetingDays, startTime, endTime);
    }

    /**
     * Creates a Course with the given name, title, section, credits, instructorId,
     * and meetingDays for courses that are arranged.
     * 
     * @param name         name of Course
     * @param title        title of Course
     * @param section      section of Course
     * @param credits      credit hours for Course
     * @param instructorId instructor's unity id
     * @param meetingDays  meeting days for Course as series of chars
     */
    public Course(String name, String title, String section, int credits, String instructorId, String meetingDays) {
        this(name, title, section, credits, instructorId, meetingDays, 0, 0);
    }

    /**
     * Returns the Course's name
     * 
     * @return the name
     */
    public String getName() {
        return name;

    }

    /**
     * Sets the Course's name
     * 
     * @param name the name to set
     */
    private void setName(String name) {
        // Throw exception if the name is null
        if (name == null) {
            throw new IllegalArgumentException("Invalid course name.");
        }
        // Throw exception if the name is an empty string
        // Throw exception if the name contains less than 5 character or greater than 8
        // characters
        if (name.length() < MIN_NAME_LENGTH || name.length() > MAX_NAME_LENGTH) {
            throw new IllegalArgumentException("Invalid course name.");
        }
        // Check for pattern of L[LLL] NNN
        int letterCount = 0;
        int digitCount = 0;
        boolean spaceFound = false;
        for (int i = 0; i < name.length(); i++) {
            if (!spaceFound) {
                if (Character.isLetter(name.charAt(i))) {
                    letterCount++;
                } else if (name.charAt(i) == ' ') {
                    spaceFound = true;
                } else {
                    throw new IllegalArgumentException("Invalid course name.");
                }
            } else  {
                if (Character.isDigit(name.charAt(i))) {
                    digitCount++;
                } else {
                    throw new IllegalArgumentException("Invalid course name.");
                }
            }
        }
        if (letterCount < MIN_LETTER_COUNT || letterCount > MAX_LETTER_COUNT) {
            throw new IllegalArgumentException("Invalid course name.");
        }
        if (digitCount != DIGIT_COUNT) {
            throw new IllegalArgumentException("Invalid course name.");
        }

        this.name = name;
    }

    /**
     * Returns the Course's section
     * 
     * @return the section
     */
    public String getSection() {
        return section;
    }

    /**
     * Sets the Course's section
     * 
     * @param section the section to set
     */
    public void setSection(String section) {
        if (section == null || section.length() != SECTION_LENGTH) {
            throw new IllegalArgumentException("Invalid section.");
        }
        for (int i = 0; i < section.length(); i++) {
            if (!Character.isDigit(section.charAt(i))) {
                throw new IllegalArgumentException("Invalid section.");
            }
        }
        this.section = section;
    }

    /**
     * Returns the Course's credits
     * 
     * @return the credits
     */
    public int getCredits() {
        return credits;
    }

    /**
     * Sets the Course's credits
     * 
     * @param credits the credits to set
     */
    public void setCredits(int credits) {
        if (credits < MIN_CREDITS || credits > MAX_CREDITS) {
            throw new IllegalArgumentException("Invalid credits.");
        }

        this.credits = credits;
    }

    /**
     * Returns the Course's instructor id
     * 
     * @return the instructorId
     */
    public String getInstructorId() {
        return instructorId;
    }

    /**
     * Sets the Course's instructor id
     * 
     * @param instructorId the instructorId to set
     */
    public void setInstructorId(String instructorId) {
        if (instructorId == null || "".equals(instructorId)) {
            throw new IllegalArgumentException("Invalid instructor id.");
        }

        this.instructorId = instructorId;
    }

    /**
     * Generates a hashCode for Course using all fields.
     * 
     * @return hashCode for Course
     */
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + credits;
        result = prime * result + endTime;
        result = prime * result + ((instructorId == null) ? 0 : instructorId.hashCode());
        result = prime * result + ((meetingDays == null) ? 0 : meetingDays.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((section == null) ? 0 : section.hashCode());
        result = prime * result + startTime;
        result = prime * result + ((title == null) ? 0 : title.hashCode());
        return result;
    }

    /**
     * Compares a given object to this object for equality on all fields.
     * 
     * @param obj the Object to compare
     * @return true if the objects are the same on all fields.
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Course other = (Course) obj;
        if (credits != other.credits)
            return false;
        if (endTime != other.endTime)
            return false;
        if (instructorId == null) {
            if (other.instructorId != null)
                return false;
        } else if (!instructorId.equals(other.instructorId))
            return false;
        if (meetingDays == null) {
            if (other.meetingDays != null)
                return false;
        } else if (!meetingDays.equals(other.meetingDays))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (section == null) {
            if (other.section != null)
                return false;
        } else if (!section.equals(other.section))
            return false;
        if (startTime != other.startTime)
            return false;
        if (title == null) {
            if (other.title != null)
                return false;
        } else if (!title.equals(other.title))
            return false;
        return true;
    }

    /**
     * Returns a comma separated value String of all Course fields.
     * 
     * @return String representation of Course
     */
    @Override
    public String toString() {
        if ("A".equals(meetingDays)) {
            return name + "," + title + "," + section + "," + credits + "," + instructorId + "," + meetingDays;
        }
        return name + "," + title + "," + section + "," + credits + "," + instructorId + "," + meetingDays + ","
                + startTime + "," + endTime;
    }

}
