package org.appfuse.persistence;

import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.orm.hibernate.SessionFactoryUtils;
import org.springframework.orm.hibernate.SessionHolder;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import org.appfuse.model.*;
import net.sf.hibernate.SessionFactory;
import net.sf.hibernate.Session;
import net.sf.hibernate.ObjectDeletedException;

public class ResumeDAOTest extends BaseDAOTestCase {
    //~ Instance fields ========================================================

    private Log log = LogFactory.getLog(ResumeDAOTest.class);
    private Resume resume = null;
    private ResumeDAO dao = null;
    private SessionFactory sf;

    protected void setUp() throws Exception {
        // the following is necessary for lazy loading
        sf = (SessionFactory) ctx.getBean("sessionFactory");
        // open and bind the session for this test thread.
        Session s = sf.openSession();
        TransactionSynchronizationManager.bindResource(sf, new SessionHolder(s));

        dao = (ResumeDAO) ctx.getBean("resumeDAO");
    }

    protected void tearDown() throws Exception {
        // unbind and close the session.
        SessionHolder holder = (SessionHolder)
                TransactionSynchronizationManager.getResource(sf);
        Session s = holder.getSession();
        s.flush();
        TransactionSynchronizationManager.unbindResource(sf);
        SessionFactoryUtils.closeSessionIfNecessary(s, sf);

        dao = null;
    }

    public void testGetResumeByUserId() throws Exception {
        List resumes = dao.getResumesByUserId(new Long(1));
        log.info(resumes);
        assertTrue(resumes.size() > 0);
    }

    public void testGetResume() throws Exception {
        resume = dao.getResume(new Long(1));
        log.info(resume);
        assertTrue(resume.getName() != null);
    }

    public void testSaveResume() throws Exception {
        resume = dao.getResume(new Long(1));
        assertTrue(resume.getDescription().equals("description"));
        resume.setDescription("UPDATED description");

        dao.saveObject(resume);

        if (log.isDebugEnabled()) {
            log.debug("updated resume: " + resume);
        }

        assertTrue(resume.getDescription().equals("UPDATED description"));

        // set back to original so test doesn't fail next time we run it
        resume.setDescription("description");
        dao.saveObject(resume);
    }

    public void testAddAndRemoveResume() throws Exception {
        resume = new Resume();
        resume.setDescription("description");
        resume.setName("simple test");
        resume.setObjective("objective");
        resume.setUserId(new Long(1));

        dao.saveObject(resume);
        assertTrue(resume.getName().equals("simple test"));
        assertTrue(resume.getId() != null);

        if (log.isDebugEnabled()) {
            log.debug("removing resume...");
        }

        dao.removeResume(resume);
    }

    public void testGetEducation() throws Exception {
        List list = dao.getSchools(new Long(1));
        assertTrue(list.size() > 0);

        Education e = dao.getEducation(new Long(1));
        assertTrue(e.getName() != null);
    }

    public void testAddAndRemoveEducation() throws Exception {
        Education e = new Education();
        e.setResumeId(new Long(1));
        e.setName("University of Colorado");
        e.setLocation("Boulder");
        e.setState("CO");
        e.setCountry("USA");
        dao.saveObject(e);
        assertTrue(e.getId() != null);
        if (log.isDebugEnabled()) {
            log.debug("removing education...");
        }
        dao.removeObject(e);
        try {
            e = dao.getEducation(e.getId());
            fail("Education object found in database!");
        } catch (Exception ex) {
            assertTrue("object deleted exception",
                    ex.getCause() instanceof ObjectDeletedException);
        }

    }

    public void testGetExperience() throws Exception {
        List list = dao.getWorkHistory(new Long(1));
        assertTrue(list.size() > 0);

        Experience e = dao.getExperience(new Long(1));
        assertTrue(e.getOrganizationName() != null);
    }

    public void testAddAndRemoveExperience() throws Exception {
        Experience e = new Experience();
        e.setResumeId(new Long(1));
        e.setOrganizationName("IBM Global Services");
        e.setLocation("Boulder");
        e.setTitle("Intranet Developer");
        e.setDescription("Helped develop intranet for CoBank.");

        // set dates
        Date startDate = new Date();
        startDate.setTime(startDate.getTime() - 2000000);
        e.setStartDate(startDate);
        Date endDate = new Date();
        endDate.setTime(endDate.getTime() + 1000000);
        e.setEndDate(endDate);

        if (log.isDebugEnabled()) {
            log.debug("saving... " + e);
        }

        dao.saveObject(e);
        log.debug("new id set to: " + e.getId());
        assertTrue(e.getId() != null);
        if (log.isDebugEnabled()) {
            log.debug("removing experience...");
        }
        dao.removeObject(e);
        try {
            e = dao.getExperience(e.getId());
            fail("Experience object found in database!");
        } catch (Exception ex) {
            assertTrue("object deleted exception",
                    ex.getCause() instanceof ObjectDeletedException);
        }
    }

    public void testGetReference() throws Exception {
        List list = dao.getReferences(new Long(1));
        assertTrue(list.size() > 0);

        Reference r = dao.getReference(new Long(1));
        assertTrue(r.getName() != null);
    }

    public void testAddAndRemoveReference() throws Exception {
        Reference ref = new Reference();
        ref.setResumeId(new Long(1));
        ref.setName("Alan VanNice");
        ref.setPhoneNumber("303-212-0591");
        ref.setProfessional(Boolean.TRUE);
        if (log.isDebugEnabled()) {
            log.debug("saving... " + ref);
        }
        dao.saveObject(ref);
        log.debug("new id set to: " + ref.getId());
        assertTrue(ref.getId() != null);
        if (log.isDebugEnabled()) {
            log.debug("removing reference...");
        }
        dao.removeObject(ref);

        try {
            ref = dao.getReference(ref.getId());
            fail("Reference object found in database!");
        } catch (Exception ex) {
            assertTrue("object deleted exception",
                    ex.getCause() instanceof ObjectDeletedException);
        }
    }

    public void testGetMembership() throws Exception {
        List list = dao.getMemberships(new Long(1));
        assertTrue(list.size() > 0);

        Membership mem = dao.getMembership(new Long(1));
        assertTrue(mem.getOrganizationName() != null);
    }

    public void testAddAndRemoveMembership() throws Exception {
        Membership mem = new Membership();
        mem.setResumeId(new Long(1));
        mem.setOrganizationName("Denver Chamber of Commerce");
        mem.setAffiliation("Member");
        Date startDate = new Date();
        startDate.setTime(startDate.getTime() - 2000000);
        mem.setStartDate(startDate);
        Date endDate = new Date();
        endDate.setTime(endDate.getTime() + 1000000);
        mem.setEndDate(endDate);

        if (log.isDebugEnabled()) {
            log.debug("saving... " + mem);
        }

        dao.saveObject(mem);
        log.debug("new id set to: " + mem.getId());
        assertTrue(mem.getId() != null);
        if (log.isDebugEnabled()) {
            log.debug("removing membership...");
        }
        dao.removeObject(mem);

        try {
            mem = dao.getMembership(mem.getId());
            fail("Membership object found in database!");
        } catch (Exception ex) {
            assertTrue("object deleted exception",
                    ex.getCause() instanceof ObjectDeletedException);
        }
    }

    public static void main(String[] args) {
        junit.textui.TestRunner.run(ResumeDAOTest.class);
    }
}