package com.k_int.aggr2.mimsy.rdf;

import java.io.Writer;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import com.k_int.aggr2.mimsy.data.ControlledReferenceDTO;
import com.k_int.aggr2.mimsy.data.DescriptionDTO;
import com.k_int.aggr2.mimsy.data.InstructionDTO;
import com.k_int.aggr2.mimsy.data.MimsyDataDTO;
import com.k_int.aggr2.mimsy.data.MimsyDateDTO;
import com.k_int.aggr2.mimsy.data.MimsyMediaDataDTO;
import com.k_int.aggr2.mimsy.data.MimsyObjectDataDTO;
import com.k_int.aggr2.mimsy.data.NameDTO;
import com.k_int.aggr2.mimsy.data.RightsDTO;
import com.k_int.aggr2.mimsy.data.TextTypePairDTO;
import com.k_int.aggr2.mimsy.data.TitleDTO;
import com.k_int.aggr2.mimsy.data.conversion.AbstractObjectFormatConverter;
import com.k_int.aggr2.mimsy.data.util.MimsyHelper;
import com.k_int.mimsy.ref.DataException;
import com.k_int.mimsy.ref.MediaRecordTypeEnum;

public class RDFObjectConverter extends AbstractObjectFormatConverter {

	private Writer writer;
	
	public RDFObjectConverter(Writer writer)
	{
		this.writer=writer;
	}
	
	@Override
	protected void convertDate(String date_str, Set<MimsyDateDTO> dates)
			throws DataException 
			{
		if(dates.size()==0)
			return;
		try
		{
			writer.write("<");
			writer.write(date_str);
			writer.write("Links>");
	     	Iterator<MimsyDateDTO> i = dates.iterator();
	     	while(i.hasNext())
	     	{
	        	MimsyDateDTO date = i.next();
	        	writer.write("<");
	    		writer.write(date_str);
	    		writer.write("Link>");
	     		convert(date_str,date.getDateText());
	     		convert(date_str+"Earliest",date.getEarliest());
	     		convert(date_str+"Latest",date.getLatest());
	     		convert(date_str+"Method",date.getMethod());
	     		convert(date_str+"Era",date.getEra());
	     		String rel = "undefined" 	;
	     		if(date.getRelation()!=null)
	     			rel=date.getRelation();
	     		
	     		convert(date_str+"Relation",rel);
	     		    
	     		convert("mo:prior",Boolean.toString(date.getPrior()));
	 			RDFHelper.writeAttribution(writer, date_str, date.getAttribution());
	     				
	     		writer.write("</");
	    		writer.write(date_str);
	    		writer.write("Link>");;         		            		
	     	}
	     	writer.write("</");
			writer.write(date_str);
			writer.write("Links>");
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertDescriptions(Set<DescriptionDTO> descriptions)
			throws DataException {
		if(descriptions.size()==0)
			return;
		try
		{
	        writer.write("<mo:otherDescriptionLinks>");
	        Iterator<DescriptionDTO> i = descriptions.iterator();
	        while(i.hasNext())
	        {
	        	DescriptionDTO description = i.next();
	    		if(description.getDescription()==null)
	    			continue;
	        	writer.write("<mo:otherDescriptionLink>");
	        	convert("mo:otherDescription",description.getDescription());
	        	String type="undefined";
	        	if(description.getType()!=null)
	        		type=description.getType();
	        	convert("mo:otherDescriptionType",type);
	        	convert("mo:prior",Boolean.toString(description.getPrior()));
	        	convert("mo:descriptionAuthor",description.getSource());
	        	convert("mo:descriptionDate",description.getDate());   		
	        	writer.write("</mo:otherDescriptionLink>");
	        }
	        writer.write("</mo:otherDescriptionLinks>");
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}
       
	}

	@Override
	protected void convertFunctionalClassification(Set<NameDTO> functional_classification)
			throws DataException {
		if(functional_classification.size()==0)
			return;
		 try
		 {
	         writer.write("<mo:functionalClassificationLinks>");
	         Iterator<NameDTO> i = functional_classification.iterator();
	         while(i.hasNext())
	         {
	         	NameDTO name = i.next();
	         	if(name.getName()==null)
	         		continue;
	         		    
	         	writer.write("<mo:functionalClassificationLink>");
	         	convert("mo:functionalClassification",name.getName());
	         	String type="undefined";
	         	if(name.getType()!=null)
	         		type=name.getType();
	         	
	         	convert("mo:functionalClassificationType",type);
	         	convert("mo:prior",Boolean.toString(name.getPrevious()));
	         	writer.write("</mo:functionalClassificationLink>");
	         }
	         writer.write("</mo:functionalClassificationLinks>");
		 }
		 catch(Exception e)
		 {
			 throw new DataException(e);
		 }
	}

	@Override
	protected void convertNames(Set<NameDTO> names) throws DataException 
	{
		if(names.size()==0)
			return;
		try
		{
			writer.write("<mo:nameLinks>");
	     	Iterator<NameDTO> i = names.iterator();
	     	while(i.hasNext())
	     	{
	     		NameDTO name = i.next();
	     		if(name.getName()==null)
	     			continue;	     		    
	     		writer.write("<mo:nameLink>");
	     		convert("mo:name",name.getName());
	     		String type="undefined";
	     		if(name.getType()!=null)
	     			type=name.getType();
	     		convert("mo:nameType",type);
	     		convert("mo:prior",Boolean.toString(name.getPrevious()));      		
	     		writer.write("</mo:nameLink>");
	     	}
	     	writer.write("</mo:nameLinks>");
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertOtherNumbers(Set<TextTypePairDTO> other_numbers)
			throws DataException {
		if(other_numbers.size()==0)
			return;
		
		try
		{
    		writer.write("<mo:otherNumberLinks>");
        	Iterator<TextTypePairDTO> i = other_numbers.iterator();
        	while(i.hasNext())
        	{
        		writer.write("<mo:otherNumberLink>");
        		TextTypePairDTO pair = i.next();        		
        		convert("mo:otherNumber",pair.getText());  
        		String type="undefined";
        		if(pair.getType()!=null)
        			type=pair.getType();
        		convert("mo:otherNumberType",type);
        		
        		writer.write("</mo:otherNumberLink>");
        	}
        	writer.write("</mo:otherNumberLinks>");
        }
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertOtherTitles(Set<TitleDTO> other_titles) throws DataException {
		if(other_titles.size()==0)
			return;
		
		try
		{
        	writer.write("<mo:otherTitleLinks>");
        	Iterator<TitleDTO> i = other_titles.iterator();
        	while(i.hasNext())
        	{
        		TitleDTO title = i.next();
        		if(title.getTitle()==null)
        			continue;
        		writer.write("<mo:otherTitleLink>");
        		convert("mo:otherTitle",title.getTitle());
        		String type="undefined";
        		if(title.getType()!=null)
        			type=title.getType();
        		convert("mo:otherTitleType",type);
        		convert("mo:prior",Boolean.toString(title.getPrior()));
        	
        		RDFHelper.writeAttribution(writer, "otherTitle", title.getAttribution());
        		
        		writer.write("</mo:otherTitleLink>");
        	}
        	writer.write("</mo:otherTitleLinks>");
        }
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertRights(RightsDTO rights) throws DataException {
		if(rights==null)
			return;
		try
		{
         	writer.write("<mo:rights>");  
         	writer.write("<mo:rightsStatement>");  
         	convert("mo:rightsCreditLine",rights.getCreditLine());
         		convert("mo:rightsDetails",rights.getDetails());
         		convert("mo:rightsFromDate",rights.getFromDate());
         		convert("mo:rightsToDate",rights.getToDate());
         		String type="undefined";
         		if(rights.getType()!=null)
         			type=rights.getType();
         		convert("mo:rightsType",type);
         		
         		convert("mo:rightsHolder",rights.getHolder());
         		writer.write("</mo:rightsStatement>");  
         	writer.write("</mo:rights>");            	
        }
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertControlledRefs(String prefix,
			Set<ControlledReferenceDTO> controlled_refs) throws DataException{
		if(controlled_refs.size()==0)
			return;
		try
		{			
        	writer.write("<");
        	writer.write(prefix);
        	writer.write("Links>");
        	Iterator<ControlledReferenceDTO> i = controlled_refs.iterator();
        	while(i.hasNext())
        	{
        		ControlledReferenceDTO ref = i.next();
        		if(ref.getIdentifier()==null)
        			continue;
        		writer.write("<");
            	writer.write(prefix);
            	writer.write("Link>");
            	writer.write("<");
            	writer.write(prefix);
            	writer.write("Reference ");
                writer.write("rdf:resource=\"urn://mol/");
                writer.write(MimsyHelper.encodeForXml(ref.getIdentifier()));
                writer.write("\"/>");
                String rel ="undefined";
                if(ref.getRelationship()!=null)
                	rel=ref.getRelationship();
                
                convert(prefix+"Relation",rel);
              
    			writer.write("</");
            	writer.write(prefix);
            	writer.write("Link>");
        	}
        	writer.write("</");
        	writer.write(prefix);
        	writer.write("Links>");      	
	            
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}
	}

	@Override
	protected void convertMediaLinks(Map<Integer,MimsyMediaDataDTO> linked_media)
			throws DataException {
		if(linked_media.size()==0)
			return;
        
		try
		{
        	writer.write("<mo:mediaLinks>");
        	Iterator<Map.Entry<Integer, MimsyMediaDataDTO>> i = linked_media.entrySet().iterator();
        	while(i.hasNext())
        	{
        		Map.Entry<Integer, MimsyMediaDataDTO> entry =i.next();
        		MimsyMediaDataDTO ref = entry.getValue();
        		Integer key=entry.getKey();
        		writer.write("<mo:mediaLink>");
        		writer.write("<mo:mediaReference rdf:resource=\"urn://mol/");
	            writer.write(MimsyHelper.encodeForXml(ref.getMimsyIdentifier()));
	            writer.write("\"/>");
	            if(key!=null)
	            	convert("mo:mediaIndex",key.toString());
                if(ref.getRecordType()==MediaRecordTypeEnum.IMAGE)
                {
                	convert("mo:previewMediaLocation",ref.getPreviewRelativePath());
                	convert("mo:midMediaLocation",ref.getMidRelativePath());
                	convert("mo:largeMediaLocation",ref.getLargeRelativePath());
                	convert("mo:originalMediaLocation",ref.getLargeDonorRelativePath());	 	              
                }
                else if(ref.getDonorRelativePath()!=null)
                {
                	convert("mo:originalMediaLocation",ref.getDonorRelativePath());
                }
                String rel="undefined";
                if(ref.getRelationship()!=null)
                	rel=ref.getRelationship();
                convert("mo:mediaRelation",rel);
	                     
	            writer.write("</mo:mediaLink>");
        	}
        	writer.write("</mo:mediaLinks>");    
        	
        }
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	
	protected void convertStringList(String name, Set<String> data)
			throws DataException 
			{
		try
		{
			writer.write("<");
			writer.write(name);
			writer.write("Links>");
			Iterator<String> m = data.iterator();
			while(m.hasNext())
			{
				writer.write("<");
				writer.write(name);
				writer.write("Link>");
				convert(name,m.next()); 
				writer.write("</");
				writer.write(name);
				writer.write("Link>");				
			}
			writer.write("</");
			writer.write(name);
			writer.write("Links>");
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	
	protected void convert(String elementVal, String val) throws DataException 
	{
		try
		{
			RDFHelper.writeElement(writer,elementVal, null, val);
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}
	}

	@Override
	protected void convertConfAndLastUpdate(MimsyDataDTO data)
			throws DataException {
		try
		{
			RDFHelper.writeConfStatusAndLastUpdate(writer,data);
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	@Override
	protected void convertInstructions(Set<InstructionDTO> instructions)
			throws DataException {
		try
		{
			RDFHelper.writeInstructions(writer,instructions);
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}

	
	public void prefix(MimsyObjectDataDTO data) throws DataException {
		try
        {          
           RDFHelper.writePreamble(writer, "resource", data.getMimsyIdentifier());
        }
        catch(Exception ex)
        {
            throw new DataException(ex);
        }      

	}

	
	public void suffix(MimsyObjectDataDTO data) throws DataException {
		try
		{
			RDFHelper.writeEndAndFlush(writer, "resource");
		}
		catch(Exception e)
		{
			throw new DataException(e);
		}

	}
}
