/**
 * DefaultTitleSearchStrategy.java
 * Created May 14, 2008
 * Copyright (c) TANDBERG Television 2007-2008
 */
package com.tandbergtv.watchpoint.pmm.title.provider.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;

import com.tandbergtv.watchpoint.pmm.dao.hibernate.HibernateContext;
import com.tandbergtv.watchpoint.pmm.entities.Title;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleProvider;
import com.tandbergtv.watchpoint.pmm.title.provider.ITitleSearchStrategy;
import com.tandbergtv.watchpoint.search.QueryBuilder;
import com.tandbergtv.workflow.util.SearchCriteria;

/**
 * The default title search strategy implementation which uses a database as the
 * repository
 * 
 * @author Sahil Verma
 */
public class DefaultTitleSearchStrategy implements ITitleSearchStrategy {

	private static final Logger logger = Logger
			.getLogger(DefaultTitleSearchStrategy.class);

	private ITitleProvider provider;

	/**
	 * {@inheritDoc}
	 */
	public ITitleProvider getTitleProvider() {
		return this.provider;
	}

	/**
	 * {@inheritDoc}
	 */
	public void setTitleProvider(ITitleProvider provider) {
		this.provider = provider;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.tandbergtv.watchpoint.pmm.title.provider.ITitleSearchStrategy#count
	 * (com.tandbergtv.workflow.util.SearchCriteria)
	 */
	public int count(SearchCriteria criteria) {
		int count = 0;

		Session session = getSession();
		Query query = session.createQuery(getCountQuery(criteria));
		count = Integer.parseInt(query.uniqueResult().toString());

		return count;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.tandbergtv.watchpoint.pmm.title.provider.ITitleSearchStrategy#search
	 * (com.tandbergtv.workflow.util.SearchCriteria)
	 */
	public Collection<Title> search(SearchCriteria criteria) {
		Collection<Title> titles = new ArrayList<Title>();
		int index = criteria.getStartingRecordNumber();
		int count = criteria.getRecordsCount();
		String s = getQuery(criteria);

		logger.debug("Executing query :" + System.getProperty("line.separator")
				+ s);

		Session session = getSession();

		Query query = session.createQuery(s);

		query.setFirstResult(index);
		query.setMaxResults(count == 0 ? Integer.MAX_VALUE : count);

		List<?> result = query.list();

		titles = getTitles(result);

		return titles;
	}

	private Collection<Title> getTitles(List<?> result) {
		Collection<Title> titles = new ArrayList<Title>();

		for (int i = 0; i < result.size(); i++) {
			if (result.get(i) instanceof Title) {
				Title title = Title.class.cast(result.get(i));
				titles.add(title);
			} else {
				Object[] objs = (Object[]) result.get(i);
				for (Object o : objs) {
					if (o instanceof Title) {
						Title title = Title.class.cast(o);
						titles.add(title);
					}
				}
			}
		}
		return titles;
	}

	/**
	 * Returns the select HQL query for the specified criteria
	 * 
	 * @param criteria
	 * @return
	 */
	public String getQuery(SearchCriteria criteria) {
		return QueryBuilder.newInstance().buildQuery(criteria);
	}

	/**
	 * Returns the count HQL query for the specified criteria
	 * 
	 * @param criteria
	 * @return
	 */
	public String getCountQuery(SearchCriteria criteria) {
		return QueryBuilder.newInstance().buildCountQuery(criteria);
	}

	private Session getSession() {
		return HibernateContext.getContext().getCurrentSession();
	}	
}
