/*
 * File: CourseBean.java
 * Created on Mar 27, 2005
 */
package com.dragonsoft.tryapp.ejb.session;

import java.io.File;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.FinderException;
import javax.ejb.RemoveException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import com.dragonsoft.tryapp.common.ActivityObj;
import com.dragonsoft.tryapp.common.AssignmentObj;
import com.dragonsoft.tryapp.common.CourseObj;
import com.dragonsoft.tryapp.common.UserCredentials;
import com.dragonsoft.tryapp.common.exceptions.ExceptionHandler;
import com.dragonsoft.tryapp.ejb.entity.interfaces.ActivityFS;
import com.dragonsoft.tryapp.ejb.entity.interfaces.ActivityFSHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.AssignmentFS;
import com.dragonsoft.tryapp.ejb.entity.interfaces.AssignmentFSHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.AssignmentKey;
import com.dragonsoft.tryapp.ejb.entity.interfaces.Course;
import com.dragonsoft.tryapp.ejb.entity.interfaces.CourseFS;
import com.dragonsoft.tryapp.ejb.entity.interfaces.CourseFSHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.CourseHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.CourseKey;
import com.dragonsoft.tryapp.ejb.entity.interfaces.CoursePK;
import com.dragonsoft.tryapp.ejb.entity.interfaces.GraderHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.Instructor;
import com.dragonsoft.tryapp.ejb.entity.interfaces.InstructorHome;
import com.dragonsoft.tryapp.ejb.entity.interfaces.SubmissionRoster;
import com.dragonsoft.tryapp.ejb.entity.interfaces.SubmissionRosterHome;
import com.dragonsoft.tryapp.ejb.session.interfaces.AssignmentFinder;
import com.dragonsoft.tryapp.ejb.session.interfaces.AssignmentFinderHome;

import fireTester.tests.batch.BatchCommand;
import fireTester.tests.batch.BatchTest;
import fireTester.tests.batch.BatchTestUnit;


/**
 * CourseControllerBean: A Bean implementation responsible for
 * processing requests on course information. This bean can be used
 * to find the assignments within a given class for a particular student.
 * The Assignments associated with an Instructor, as well as a Grader.
 * 
 * @ejb.bean name="CourseController"
 *           display-name="Name for Course"
 *           description="Description for Course"
 *           jndi-name="ejb/CourseController"
 *           type="Stateless"
 *           view-type="remote"
 */
public class CourseControllerBean implements SessionBean {

    //cached beans
    private InstructorHome ih;
    private GraderHome gh;
    private CourseHome ch;
    private SubmissionRosterHome sh;
    private AssignmentFinderHome fh;
    
    /**
     * 
     */
    public CourseControllerBean() {
        super();
    }

    /* 
     * @see javax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
     */
    public void setSessionContext(SessionContext arg0)throws EJBException,RemoteException {}

    /* 
     * @see javax.ejb.SessionBean#ejbRemove()
     */
    public void ejbRemove() throws EJBException, RemoteException {
    }

    /* 
     * @see javax.ejb.SessionBean#ejbActivate()
     */
    public void ejbActivate() throws EJBException, RemoteException {
       init();
    }

    /* 
     * @see javax.ejb.SessionBean#ejbPassivate()
     */
    public void ejbPassivate() throws EJBException, RemoteException {
    }
    
	/**
	 * Create method Standard
	 * @ejb.create-method  view-type = "remote"
	 */
	public void ejbCreate() throws javax.ejb.CreateException {
		init();
	}
	
	/**
	 * Gets all the courses a student is enrolled in. The courses
	 * should be fully populated with information that contains the
	 * assignments and activities associated within them.
	 * 
	 * @param uc
	 * @return a list of courses
	 * 
	 * @ejb.interface-method  view-type = "remote"
	 */
	public List getStudentCourses(UserCredentials uc) throws RemoteException{
		
	    List list = new ArrayList();
	    Collection collection = null;
	    Iterator iter = null;
	    SubmissionRoster roster = null;
	    try {
	    	if(uc == null || uc.getUsername()==null){
	    		System.out.println("UC IS NULL");
	    	}
	        collection = sh.findCoursesByStudent(uc.getUsername());
	        
	        iter = collection.iterator();
	        while(iter.hasNext()){
	        	roster = (SubmissionRoster)iter.next();
	        	list.add(roster.getItemKey().getCourseID());
	        }
	        String[] ids = new String[list.size()];
	        list.toArray(ids);
	        list = this.constructCourses(ids);
	   
	    } catch (FinderException e) {
	    	System.out.println("FINDER EXCEPTION");
	    	list = new ArrayList();
	    	return list;
	    } catch (RemoteException e) {
	        ejbActivate();
	        throw e;
	    }
	// This was where the insertion of a unit test.    newCourse();
	    return list;
	}
	
	private void newCourse(){
		try {
			Context ctx = new InitialContext();
			Object o = ctx.lookup(CourseFSHome.JNDI_NAME);
			CourseFSHome home = (CourseFSHome)PortableRemoteObject.narrow(o,CourseFSHome.class);
			o = ctx.lookup(AssignmentFSHome.JNDI_NAME);
			AssignmentFSHome ah = (AssignmentFSHome)PortableRemoteObject.narrow(o,AssignmentFSHome.class);
			o = ctx.lookup(ActivityFSHome.JNDI_NAME);
			ActivityFSHome acth = (ActivityFSHome)PortableRemoteObject.narrow(o,ActivityFSHome.class);
			
			String coursenum = "4003252";
			
			if(home.findByPrimaryKey(new CourseKey("20043",coursenum))== null){
				
			
			CourseFS fs = home.create("20043",coursenum,"TestCourse");
			//CourseKey key = home.create("20043",coursenum,"07","TestCourse2");
			CourseKey key = fs.getKey();
			
			AssignmentFS assignment = ah.create(key,"Strings and Things","1");
			AssignmentKey asskey = assignment.getKey();
			ActivityFS actFS = acth.create(asskey,"1","Parse this");
			actFS.addRequiredFile("StringParser.java");
			actFS.addRejectedFile("*.class");
			actFS.addOptionalFile("*.java");
			actFS.setDueDate(new Date());
			BatchTest test[] = new BatchTest[1];
			test[0] = getTests();
			actFS.setTests(test);
			}
		} catch (NamingException e) {
			ExceptionHandler.logException(e,this);
		} catch (RemoteException e) {
			ExceptionHandler.logException(e,this);
		} catch (CreateException e) {
			ExceptionHandler.logException(e,this);
		} catch (FinderException e){
			ExceptionHandler.logException(e,this);
		}
	
		
	}
	
	private BatchTest getTests(){
		final long MB = 1024000L;
		final long S = 1000L;
		final String[] environment = new String[]{"PATH=.:/usr/java/bin:/usr/local/gnu/bin/"};
		BatchTestUnit[] units = new BatchTestUnit[2]; 
		BatchCommand[] passCommand = new BatchCommand[1];
		passCommand[0] = new BatchCommand("javac *.java",
				30000L, null, null);
		
		units[0] = new BatchTestUnit(
				null, // pre_commands
				null, // commands
				passCommand, // check pass command
				null, // pass_post_commands
				null, // fail_post_commands
				false, // required_test
				1 // next unit id
					  );
		
		BatchCommand[] execute = new BatchCommand[1];
		String command = "java HelloWorld";
//		if(!pass)
//			command += " WhatsMyName";
		execute[0] = new BatchCommand(command, 10000L, 
				"stdOut.txt", "errOut.txt");
		BatchCommand[] diff = new BatchCommand[2];
		diff[0] = new BatchCommand("diff stdOut.txt expectedStdOut.txt", 5*S, "stdDiffResults.txt", null);
		diff[1] = new BatchCommand("diff errOut.txt expectedErrOut.txt", 5*S, "errDiffResults.txt", null);
		
		units[1] = new BatchTestUnit(
				null, // pre_commands
				execute, // commands
				diff, // check pass command
				null, // pass_post_commands
				null, // fail_post_commands
				false, // required_test
				-1 // next_unit
					  );

		
		
		BatchTest test = new BatchTest(units, 1*MB, environment, null, null);
		
		
		return test;
	}
	
	/**
	 * Get all the courses a professor is teaching.
	 * 
	 * @param uc
	 * @return a list of courses
	 * 
	 * @ejb.interface-method  view-type = "remote"
	 */
	public List getProfessorCourses(UserCredentials uc) throws RemoteException{
	    List list = null;
	    try {
		
	        list = new ArrayList(ih.findCourses(uc.getUsername()));
	        String[] courses = new String[list.size()];
	        for(int i=0;i<list.size();i++){
	        	courses[i] = ((Instructor)list.get(i)).getItemKey().courseID;
	        	// this has to be redone this is bad
	        }
	        list = constructCourses(courses);
	    } catch (FinderException e) {
	    	list = new ArrayList();
	    	return list;
	    } catch (RemoteException e) {
	        ejbActivate();
	        //getProfessorCourses( uc );
	        throw e;
	    }
	   
	    return list;
	}
	
	/**
	 * Get all the courses a grader is enrolled in
	 * 
	 * @param uc
	 * @return a list of courses
	 * 
	 * @ejb.interface-method  view-type = "remote"
	 */
	public List getGraderCourses(UserCredentials uc) throws RemoteException{
	    List list = null;
	    try {
		
	        list = new ArrayList(gh.findCourses(uc.getUsername()));
	        CoursePK[] pk = new CoursePK[list.size()];
	        for(int i = 0 ; i< list.size();i++){
	        	
	        }
	        list = null; // until Grader is redone.
	    } catch (FinderException e) {
	    	list = new ArrayList();
	    	return list;
	    } catch (RemoteException e) {
	        ejbActivate();
	        throw e;
	    }
	   
	    return list;
	}
	
	/**
	 * Add a new course
	 * 
	 * @param course the course
	 * @return if the course was added
	 * 
	 * @ejb.interface-method  view-type = "remote"
	 */
	public boolean addCourse( CourseObj course ) {
	    try {	
	        
	        //create the directory structure
			String pathToFiles = com.dragonsoft.tryapp.support.TryFileSystem
				.getAssignmentDirectory()
				+ File.separator 
				+ course.getCourseID() 
				+ File.separator;
			
			Iterator aIterator = course.getAssignments().iterator();
			
			while (aIterator.hasNext()) {
			    AssignmentObj ao = (AssignmentObj)aIterator.next();
			    Iterator acIterator = ao.getActivities().iterator();
			    
			    while (acIterator.hasNext()) {
			        ActivityObj aco = (ActivityObj)acIterator.next();
			        File file = new File( pathToFiles+ao.getAssignmentName()+aco.getActivityName());
			        file.mkdirs();
			    }
			}
				
			ch.create(course);	
	    } catch (Exception e) {
	        return false;
	    } 
	    return true;
	}
	
	private List constructCourses(String[] courseIDs){
		int size = courseIDs.length;
		List rtVal = new ArrayList();
		CourseObj crs = null;
		for(int i =0;i<size;i++){
			try {
				Course course = ch.findByPrimaryKey(new CoursePK(courseIDs[i]));
				crs = course.getCourse();
				AssignmentFinder finder = fh.create();
				AssignmentObj[] assigns = finder.getAssociatedAssignments(courseIDs[i]);
				finder.remove();
				for(int k =0 ; k< assigns.length;k++)
					crs.addAssignment(assigns[k]);
				rtVal.add(crs);
			} catch (RemoteException e) {
				ExceptionHandler.logException(e,this);
			} catch (CreateException e) {
				ExceptionHandler.logException(e,this);
			} catch (RemoveException e) {
				ExceptionHandler.logException(e,this);
			} catch (FinderException e) {
				ExceptionHandler.logException(e,this);
			}
			
		}
		return rtVal;
	}

	private void init(){
		 try {
            InitialContext context = new InitialContext();
            Object obj = context.lookup(SubmissionRosterHome.JNDI_NAME);
			sh = (SubmissionRosterHome) PortableRemoteObject.narrow( obj, 
			        SubmissionRosterHome.class );
			
			obj = context.lookup(InstructorHome.JNDI_NAME);
			ih = (InstructorHome) PortableRemoteObject.narrow( obj, 
			        InstructorHome.class );
			
			obj = context.lookup(GraderHome.JNDI_NAME);
			gh = (GraderHome) PortableRemoteObject.narrow( obj, 
			        GraderHome.class );
			
			obj = context.lookup(CourseHome.JNDI_NAME);
			ch = (CourseHome) PortableRemoteObject.narrow( obj, 
			        CourseHome.class );
            
			obj = context.lookup(AssignmentFinderHome.JNDI_NAME);
			fh = (AssignmentFinderHome) PortableRemoteObject.narrow( obj, 
			        AssignmentFinderHome.class );
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println( "ERROR: Instantiating CourseControllerBean");
        }
	}
}