/**
 * Copyright 2008-2009 DRIVER PROJECT (Bielefeld University)
 * Original author: Marek Imialek <marek.imialek at uni-bielefeld.de>
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dnetlib.data.sts.mock.lls;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.io.FileUtils;

import pl.edu.icm.yadda.process.sync.CountingIteratorWrapper;
import pl.edu.icm.yadda.service2.YaddaObjectID;
import pl.edu.icm.yadda.service2.archive.IProtocolRequest;
import pl.edu.icm.yadda.service2.catalog.CountingIterator;
import pl.edu.icm.yadda.service2.exception.ServiceException;
import pl.edu.icm.yadda.service3.ArchiveObject2Meta;
import pl.edu.icm.yadda.service3.ArchiveObjectFacade;
import pl.edu.icm.yadda.service3.ArchiveObjectPath;
import pl.edu.icm.yadda.service3.archive.IArchiveFacade2;
import eu.dnetlib.data.sts.lls.LLSStoreFacade;

/**
 * The Class ossLssArchiveMock.
 * 
 * @author <a href="mailto:marek.imialek at uni-bielefeld.de">Marek Imialek</a>
 */
public class ossLssArchiveMock implements IArchiveFacade2{
	
	/** The Constant tmpStoragePath. */
	private static final String tmpStoragePath = ossLlsStorageMock.tmpStoragePath; 

	/** The Constant protocol. */
	private static final String protocol = LLSStoreFacade.protocol; 
	
	/** The Constant mainStoragePath. */
	public static final String mainStoragePath = 
				(tmpStoragePath+"/"+protocol).replace("://", "");
	
	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#fetchPartContent(java.lang.String, java.lang.String)
	 */
	@Override
	public InputStream fetchPartContent(String arg0, String arg1)
			throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getArchiveId()
	 */
	@Override
	public String getArchiveId() throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getFeatures(java.util.Set)
	 */
	@Override
	public Set<String> getFeatures(Set<String> arg0) throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getObject(pl.edu.icm.yadda.service2.YaddaObjectID, java.lang.String[], boolean)
	 */
	@Override
	public ArchiveObjectFacade getObject(YaddaObjectID arg0, String[] arg1,
			boolean arg2) throws ServiceException {
		
		String objectString = 
			arg0.getId().replace("yar://", mainStoragePath+"/");
		
		File file = new File(objectString);
		
		if (file.exists()) {

			YaddaObjectID yo = new YaddaObjectID(arg0.getId());
			Map<String, List<YaddaObjectID>> children = 
				new HashMap<String,List<YaddaObjectID>>();
			List<YaddaObjectID> yaddaObjs = new ArrayList<YaddaObjectID>();
			yaddaObjs.add(yo);
			children.put("1", yaddaObjs);
			
			ArchiveObjectFacade object = new ArchiveObjectFacade();
			object.setChildren(children);
			object.setId(arg0);
			
			try {
				object.addPart("BasicContent", "xml",
						new ByteArrayInputStream(
								FileUtils.readFileToByteArray(file)));

			} catch (IOException e) {
				throw new ServiceException(e);
			}

			return object;
		} else {
			
			return null;
		}
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getObject(pl.edu.icm.yadda.service2.YaddaObjectID, java.lang.String[], boolean, boolean)
	 */
	@Override
	public ArchiveObjectFacade getObject(YaddaObjectID arg0, String[] arg1,
			boolean arg2, boolean arg3) throws ServiceException {
		
		File file = new File(mainStoragePath+"/"+arg0.getId());
		if (file.exists()) {
			ArchiveObjectFacade object = new ArchiveObjectFacade();
			object.setId(arg0);
			object.addPart("BasicContent", "xml",
					new ByteArrayInputStream(
							"I am a content of dummyObject!".getBytes()));
			return object;
		} else {
			File file1 = new File(mainStoragePath);
			String[] filesList = file1.list();
			
			if (filesList != null && filesList.length > 0) {
				for (int i=0; i<filesList.length; i++){
					File file3 = new File(mainStoragePath+"/"+
							filesList[i] +"/"+ arg0.getId());
					
					if (file3.exists()){		
						ArchiveObjectFacade object = new ArchiveObjectFacade();
						object.setId(arg0);
						object.addPart("BasicContent", "xml",
								new ByteArrayInputStream(
										"I am a content of dummyObject!".getBytes()));
						return object;
					}
				}
			}	
			return null;
		}
	}

	 /* (non-Javadoc)
         * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getObject(pl.edu.icm.yadda.service2.YaddaObjectID, java.lang.String[], boolean, boolean, boolean)
         */
        @Override
        public ArchiveObjectFacade getObject(YaddaObjectID arg0, String[] arg1,
                        boolean arg2, boolean arg3, boolean arg4) throws ServiceException {
		
        	String objId = arg0.getId();
        	if(objId.contains(protocol))
        		objId = objId.replace(protocol, "");
        	
        	String path =mainStoragePath+"/"+objId;
        	
        	if(objId.contains(mainStoragePath))
        		path = objId;
        		
        	File file = new File(path);
        	
    		if (file.exists()) {
    			StringBuffer sb = new StringBuffer();
    			try {
    				FileInputStream fstream = new FileInputStream(mainStoragePath+"/"+objId);
    				DataInputStream in = new DataInputStream(fstream);
    				BufferedReader br = new BufferedReader(new InputStreamReader(in));
    				String strLine; 
    				while ((strLine = br.readLine()) != null)   {
    					sb.append(strLine);
    				}
    				in.close();
    			}catch (Exception e){
    				System.err.println("Error: " + e.getMessage());
    			}
 
    			ArchiveObjectFacade object = new ArchiveObjectFacade();
    			object.setId(arg0);
    			object.addPart("BasicContent", "xml",
    					new ByteArrayInputStream(
    							sb.toString().getBytes()));
    			object.setPath(file.getAbsolutePath());
				
    			return object;
    		} else {
    			File file1 = new File(mainStoragePath);
    			String[] filesList = file1.list();
    			
    			if (filesList != null && filesList.length > 0) {
    				
    				for (int i=0; i<filesList.length; i++){
    					File file3 = new File(mainStoragePath+"/"+
    							filesList[i] +"/"+ objId);
    					
    					if (file3.exists()){		
    						ArchiveObjectFacade object = new ArchiveObjectFacade();
    						object.setId(arg0);
    						object.addPart("BasicContent", "xml",
    								new ByteArrayInputStream(
    										"I am a content of dummyObject!".getBytes()));
    						object.setPath(file3.getAbsolutePath());

    						return object;
    					}
    				}
    			}	
    			return null;
    		}
 	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getObject(pl.edu.icm.yadda.service2.YaddaObjectID, java.lang.String[], boolean, pl.edu.icm.yadda.service2.archive.IProtocolRequest[])
	 */
	@Override
	public ArchiveObjectFacade getObject(YaddaObjectID arg0, String[] arg1,
			boolean arg2, IProtocolRequest[] arg3) throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getObjectWithAllParts(pl.edu.icm.yadda.service2.YaddaObjectID, boolean)
	 */
	@Override
	public ArchiveObjectFacade getObjectWithAllParts(YaddaObjectID arg0,
			boolean arg1) throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#getOptionalObject(pl.edu.icm.yadda.service2.YaddaObjectID, java.lang.String[], boolean, boolean)
	 */
	@SuppressWarnings("unchecked")
	@Override
	public ArchiveObjectFacade getOptionalObject(YaddaObjectID arg0,
			String[] arg1, boolean arg2, boolean arg3) throws ServiceException {
		
		arg0.setId(arg0.getId().replace("/tmp/yar/", ""));
		
		File file = new File(mainStoragePath+"/"+arg0.getId());
	
		if (file.exists()) {
			ArchiveObjectFacade object = new ArchiveObjectFacade();
			object.setId(arg0);
			return object;
		} else {
			File file1 = new File(mainStoragePath);
			String[] filesList = file1.list();
			
			if (filesList != null && filesList.length > 0) {
				for (int i=0; i<filesList.length; i++){
					File file3 = new File(mainStoragePath+"/"+
							filesList[i] +"/"+ arg0.getId());
					if (file3.exists()){	
						ArchiveObjectFacade object = new ArchiveObjectFacade();
						object.setId(arg0);
						return object;
					}
				}
				
				Collection files = FileUtils.listFiles(new File(mainStoragePath), null, true);
				for (Iterator iterator = files.iterator(); iterator.hasNext();) {
					File file5 = (File) iterator.next();
					if (file5.getName().equals(arg0.getId())) {
						ArchiveObjectFacade object = new ArchiveObjectFacade();
						YaddaObjectID yaddaId = new YaddaObjectID(file5.getAbsolutePath());
						yaddaId.setDisplayName(file5.getAbsolutePath());
						object.setId(yaddaId);
						object.setType("FILE");
						try {
							object.addPart("ext", "ext",new FileInputStream(file5.getAbsolutePath()));
						} catch (FileNotFoundException e) {
							throw new ServiceException(e);
						}
						return object;
					}
				}
			}	
			return null;
		}
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#listObjects(java.util.Date, java.util.Date, java.lang.String[], boolean)
	 */
	@Override
	public CountingIterator<ArchiveObject2Meta> listObjects(Date arg0,
			Date arg1, String[] arg2, boolean arg3) throws ServiceException {
		
		File file = new File(mainStoragePath+"/");
		ArrayList<ArchiveObject2Meta> results = new ArrayList<ArchiveObject2Meta>(); 
		Iterator<ArchiveObject2Meta> iter = searchStorage(file,arg2,results).iterator();
		
		return  new CountingIteratorWrapper<ArchiveObject2Meta>(iter);
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#listObjects(java.util.Date, java.util.Date, java.lang.String[], boolean, boolean)
	 */
	@Override
	public CountingIterator<ArchiveObject2Meta> listObjects(Date arg0,
			Date arg1, String[] arg2, boolean arg3, boolean arg4)
			throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#listObjects(java.util.Date, java.util.Date, java.lang.String[][], boolean, boolean)
	 */
	@Override
	public CountingIterator<ArchiveObject2Meta> listObjects(Date arg0,
			Date arg1, String[][] arg2, boolean arg3, boolean arg4)
			throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#queryObjects(pl.edu.icm.yadda.service3.ArchiveObjectPath, boolean)
	 */
	@Override
	public CountingIterator<ArchiveObject2Meta> queryObjects(
			ArchiveObjectPath arg0, boolean arg1) throws ServiceException {
		// TODO Auto-generated method stub
		return null;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#queryObjects(java.lang.String, boolean)
	 */
	@Override
	public CountingIterator<ArchiveObject2Meta> queryObjects(String arg0,
			boolean arg1) throws ServiceException {
		
		String objectUri = arg0;

    	if(objectUri.contains(protocol))
    		objectUri = objectUri.replace(protocol, "");
    	
    	File file = new File(mainStoragePath+"/"+objectUri);
    	
    	String[] allFiles = null;
    	ArrayList<String> objects = new ArrayList<String>();
		if (file.exists() && file.isDirectory())
    		allFiles = file.list();
    	
		if (allFiles != null && allFiles.length != 0) 
			for (int i=0; i<allFiles.length; i++)
				if(!allFiles[i].contains(".Tag"))
					objects.add(arg0+"/"+allFiles[i]);
		
		final ArrayList<String> objectsFinal = objects;

		CountingIterator<ArchiveObject2Meta> it = new CountingIterator<ArchiveObject2Meta>(){
			
			boolean status = true; 
			int counter = 0;
			
			public int count() {
				if (objectsFinal != null)
					return objectsFinal.size();
				else 
					return 0;
			}

			public boolean hasNext() {
				return status;
			}

			public ArchiveObject2Meta next() {
				ArchiveObject2Meta ao2m = new ArchiveObject2Meta();
				ao2m.setId(new YaddaObjectID(objectsFinal.get(counter)));   				
				counter++;
				if (counter >= count())
					status = false;
				
				return ao2m;
			}

			public void remove() {
				throw new RuntimeException("unsupported method!");
			}
		};	
		
		return it;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#queryUniqueObject(pl.edu.icm.yadda.service3.ArchiveObjectPath, boolean)
	 */
	@Override
	public ArchiveObject2Meta queryUniqueObject(ArchiveObjectPath arg0,
			boolean arg1) throws ServiceException {
		
		ArchiveObject2Meta object  = new ArchiveObject2Meta();
		object.setId(new YaddaObjectID(arg0.toString()));
		
		return object;
	}

	/* (non-Javadoc)
	 * @see pl.edu.icm.yadda.service3.archive.IArchiveFacade2#queryUniqueObject(java.lang.String, boolean)
	 */
	@Override
	public ArchiveObject2Meta queryUniqueObject(String arg0, boolean arg1)
			throws ServiceException {
		
		ArchiveObject2Meta object = new ArchiveObject2Meta();
		object.setId(new YaddaObjectID(arg0));
		
		return object;
	}

	/**
	 * Search storage.
	 * 
	 * @param path the path
	 * @param tag the tag
	 * @param results the results
	 * 
	 * @return the array list< archive object2 meta>
	 */
	private ArrayList<ArchiveObject2Meta> searchStorage(File path, String[] tag,
			ArrayList<ArchiveObject2Meta> results ) {
				
		String[] filesList = path.list();
		if (filesList != null) {
			for (int i=0; i<filesList.length; i++){
				File file1 = 
					new File(path.getAbsoluteFile()+
							"/"+filesList[i]);
				if (file1.isDirectory()){
					results = searchStorage(file1, tag, results);
				}
				else {
					for (int k=0; k<tag.length; k++) {
						tag[k] = tag[k].replaceAll("/", "-");
						
						if (file1.getName().equals(tag[k]+".Tag")) {
							ArchiveObject2Meta aom = new ArchiveObject2Meta();;	
							YaddaObjectID id = new YaddaObjectID(
								path.getAbsoluteFile().toString()+"/"+tag[k]+".Tag");	
							aom.setId(id);
							results.add(aom);
						}	
					}
				}
			}
		}
		
		return results;
		
	}

	@Override
	public void checkVersion() {
		// TODO Auto-generated method stub
		
	}
	
}
