package ttsolver.model;

import ifs.model.Value;
import edu.purdue.smas.timetable.data.Preferences;
import edu.purdue.smas.timetable.data.pattern.EveningTimePattern;
import edu.purdue.smas.timetable.data.pattern.GenericTimePattern;
import edu.purdue.smas.timetable.data.pattern.SaturdayTimePattern;

/**
 * Placement (value).
 * <br><br>
 * It combines room and time location
 *
 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomas Muller</a>
 * @version 1.0
 */

public class Placement extends Value {
    private TimeLocation iTimeLocation;
    private RoomLocation iRoomLocation;
    private boolean iIsInitial = false;
    
    /** Constructor
     * @param lecture lecture
     * @param timeLocation time location
     * @param roomLocation room location
     */
    public Placement(Lecture lecture, TimeLocation timeLocation, RoomLocation roomLocation) {
        super(lecture);
        iTimeLocation = timeLocation;
        iRoomLocation = roomLocation;
    }
    
    /** Time location */
    public TimeLocation getTimeLocation() { return iTimeLocation; }
    /** Room id */
    public String getRoomId() { return iRoomLocation.getId(); }
    /** Building id */
    public String getBuildingId() { return iRoomLocation.getBuildingId(); }
    /** Room location */
    public RoomLocation getRoomLocation() { return iRoomLocation; }
    /** Instructor id */
    public String getInstructorId() { return ((Lecture)variable()).getInstructorId(); }
    public String getName() { return getTimeLocation().getText()+" "+getRoomLocation().getName()+(((Lecture)variable()).getInstructorName()!=null?" "+((Lecture)variable()).getInstructorName():getInstructorId()==null?"":" "+getInstructorId()); }

    /** Is initial placement */
    public boolean isInitial() { return iIsInitial; }
    /** Is initial placement */
    public void setInitial(boolean initial) { iIsInitial=initial; }
    
    public boolean equals(Object object) {
        if (object==null || !(object instanceof Placement)) return false;
        Placement placement = (Placement)object;
        if (placement.getId()==getId()) return true; //quick check
//        if (((Lecture)placement.variable()).getClassId()!=((Lecture)variable()).getClassId()) return false;
        Lecture lecture = (Lecture)placement.variable();
        Lecture thisLecture = (Lecture)variable();
        if (lecture!=null && thisLecture!=null && lecture.getClassId()!=thisLecture.getClassId()) return false;
        return (placement.getTimeLocation()==getTimeLocation() && 
                placement.getRoomId().equals(getRoomId()) &&
                    (placement.getInstructorId()==getInstructorId() || 
                        (placement.getInstructorId()!=null && 
                            placement.getInstructorId().equals(getInstructorId())
                        )
                    )
               );
    }
    
    public String toString() {
        return variable().getName()+" "+getName();
        //return "Placement{lecture="+variable().getName()+", time="+getTimeLocation().getText()+", len="+getTimeLocation().getLength()+", instructor="+iInstructorId+", room="+iRoomLocation.getName()+", timePref="+iTimeLocation.getNormalizedPreference()+", roomPref="+iRoomLocation.getPreference()+"}";
    }
    
    
    public String getDescription() {
        return iTimeLocation.getNrMeetings()+"x"+(25*iTimeLocation.getNrHalfHoursPerMeeting())+
               (iTimeLocation.getModel()==null?"":
               (iTimeLocation.getModel() instanceof GenericTimePattern  ? " gen.":"") +
               (iTimeLocation.getModel() instanceof SaturdayTimePattern ? " Sat.":"") +
               (iTimeLocation.getModel() instanceof EveningTimePattern  ? " evn.":"")) +
               (iTimeLocation.getPreference()!=0 || iTimeLocation.getNormalizedPreference()!=0.0?", "+Preferences.getPreference(String.valueOf(iTimeLocation.getPreference())).getName().toLowerCase()+" time ("+iTimeLocation.getNormalizedPreference()+")":"")+
               (iRoomLocation.getPreference()!=0?(iRoomLocation.getPreference()>=-2 && iRoomLocation.getPreference()<=2?", "+Preferences.getPreference(String.valueOf(iRoomLocation.getPreference())).getName().toLowerCase()+" room":", "+iRoomLocation.getPreference()+" room"):"");
    }
    
    /** Distance between two placements */
    public static double getDistance(Placement p1, Placement p2) {
        if (p1.getRoomId().equals(p2.getRoomId())) return 0.0;
        RoomLocation r1=p1.getRoomLocation();
        RoomLocation r2=p2.getRoomLocation();
        long x = r1.getPosX()-r2.getPosX();
        long y = r1.getPosY()-r2.getPosY();
        return Math.sqrt((x*x)+(y*y));
    }
    /** True if the two given placements are using at one same day*/
    public static boolean shareDays(Placement p1, Placement p2) {
        return ((p1.getTimeLocation().getDayCode() & p2.getTimeLocation().getDayCode())!=0);
    }
}
