/**
 * DefaultTitlePersistenceService.java
 * Created Apr 17, 2008
 * Copyright (c) TANDBERG Television 2007-2008
 */
package com.tandbergtv.watchpoint.pmm.title;

import java.io.Serializable;
import java.util.Collection;

import org.hibernate.Session;
import org.springframework.context.ApplicationContext;

import com.tandbergtv.cms.portal.util.transaction.Transactional;
import com.tandbergtv.metadatamanager.ITTVDataModelHandler;
import com.tandbergtv.metadatamanager.exception.MetadataException;
import com.tandbergtv.metadatamanager.exception.SearchException;
import com.tandbergtv.metadatamanager.model.Asset;
import com.tandbergtv.metadatamanager.specimpl.ttv.TTVId;
import com.tandbergtv.watchpoint.pmm.dao.hibernate.ApplicationContextHelper;
import com.tandbergtv.watchpoint.pmm.dao.hibernate.HibernateContext;
import com.tandbergtv.watchpoint.pmm.entities.AssetList;
import com.tandbergtv.watchpoint.pmm.entities.IAssetList;
import com.tandbergtv.watchpoint.pmm.entities.Title;

/**
 * Default implementation of the title persistence service
 * 
 * @author Sahil Verma
 */
public class DefaultTitlePersistenceService implements ITitlePersistenceService {
	
	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.ITitlePersistenceService#create(com.tandbergtv.watchpoint.pmm.entities.Title)
	 */
	@Transactional
	public void save(Title t) {
		try {
			t.setAsset(getTTVDataModelHandler().saveAsset(t.getAsset()));
		} catch (MetadataException e) {
			throw new RuntimeException("Unable to save associcated Asset ["
					+ t.getAsset() + "] using Metadata Manager", e);
		}
		getCurrentSession().saveOrUpdate(t);
	}
	
	/*
	 * Updates just the metadata
	 */
	@Transactional
	public Title updateMetadata(Title t) {
		try {
			getTTVDataModelHandler().saveAsset(t.getAsset());
		} catch (MetadataException e) {
			throw new RuntimeException("Unable to save associcated Asset ["
					+ t.getAsset() + "] using Metadata Manager", e);
		}
		return get(t.getId());
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.ITitlePersistenceService#get(java.io.Serializable)
	 */
	@Transactional
	public Title get(Serializable id) {
		return (Title) getCurrentSession().load(Title.class, id);
	}

	/**
	 * {@inheritDoc}
	 */
	@Transactional
	public Title get(Serializable id, String version) throws SearchException {
		//get ttvId using titleId
		Title title = get(id);
		TTVId ttvId = title.getAsset().getTTVId();
		
		//get older version asset
		Asset olderVersionAsset = getTTVDataModelHandler().getAsset(ttvId, version);
		
		//wrap it in a dummy title and return 
		Title olderVersionTitle = new Title();
		olderVersionTitle.setAsset(olderVersionAsset);
		return olderVersionTitle;
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.watchpoint.pmm.title.ITitlePersistenceService#delete(java.io.Serializable)
	 */
	@Transactional
	public boolean delete(Serializable id) {
		Session session = getCurrentSession();
		Title title = (Title) session.get(Title.class, id);
		if(title == null)
			return false;
		
		//delete asset in metadata manager
		try {
			getTTVDataModelHandler().delete(title.getAsset());
		} catch (SearchException e) {
			throw new RuntimeException("Unable to delete associated Asset ["
					+ title.getAsset() + "] using Metadata Manager", e);
		}

		// Logical deletion...
		title.setIsActive(false);
		
		// Remove the list<->title relationship
		Collection<IAssetList> lists = title.getTitlelists();
		
		for (IAssetList list : lists) {
			// Careful - Title.getTitlelists() returns proxies, so fetch the actual list entity
			AssetList clone = (AssetList) session.load(AssetList.class, list.getId());
			
			clone.removeTitle(title);
			session.saveOrUpdate(clone);
		}
		
		session.saveOrUpdate(title);
		
		return true;
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.Service#getServiceName()
	 */
	public String getServiceName() {
		return "Title Persistence";
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.ServiceLifecycle#start()
	 */
	public void start() {
	}

	/* (non-Javadoc)
	 * @see com.tandbergtv.workflow.core.service.ServiceLifecycle#stop()
	 */
	public void stop() {
	}
	
	private Session getCurrentSession() {
		return HibernateContext.getContext().getCurrentSession();
	}

	private ITTVDataModelHandler getTTVDataModelHandler() {
		return (ITTVDataModelHandler) getMetadataManagerBean("TTVSpecHandler");
	}
	
	private Object getMetadataManagerBean(String beanId) {
		ApplicationContext springContext = ApplicationContextHelper.getInstance().getContext();
		return springContext.getBean(beanId);
	}
}
