/*******************************************************************************
 * Copyright (c) 2000, 2004 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.team.examples.filesystem.subscriber;

import java.nio.file.Files;

import org.apache.tools.ant.FileUtilities;
import org.eclipse.core.internal.resources.File;
import org.eclipse.core.resources.IResource;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.variants.IResourceVariant;
import org.eclipse.team.core.variants.IResourceVariantComparator;
import org.eclipse.team.examples.filesystem.CRCUtils;
import org.eclipse.ui.internal.util.BundleUtility;

import it.micegroup.voila2.cartridge.library.javaservice.FileCopyUtils;

/**
 * Provide a custom sync info that will report files that exist both 
 * locally and remotely as in-sync and will return a null base if there
 * is an incoming change.
 */
public class FileSystemSyncInfo extends SyncInfo {

	public FileSystemSyncInfo(IResource local, IResourceVariant base, IResourceVariant remote, IResourceVariantComparator comparator) {
		super(local, base, remote, comparator);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.subscribers.SyncInfo#calculateKind(org.eclipse.core.runtime.IProgressMonitor)
	 */
	protected int calculateKind() throws TeamException {
		if (getLocal().getType() != IResource.FILE) {
			return IN_SYNC;
		}
		int description = IN_SYNC;
		
		boolean localExists = FileCopyUtils.exists(getLocal());
		boolean isFolder = getLocal().getType() != IResource.FILE;
		
		if (getBase() == null) {
			if (getRemote() == null) {
				//if (!localExists) {						
					description = IN_SYNC;
				//} else {
				//	description = OUTGOING | ADDITION;
				//}
			} else {
				if (!localExists) {
					description = INCOMING | ADDITION;
				} else {
					if (!isFolder) {
						description = CONFLICTING | ADDITION;
						byte[] localBytes = Long.toString(CRCUtils.calculateCRC(
								new java.io.File(getLocal().getLocationURI()))).getBytes();
						if (compareCRC(getLocal(), getRemote(), localBytes)) {
							//Even if the remote is changed since the last generation, it is exactly the same of the local,
							//in this situation, instead of ignoring, I return an incoming change so that the base can be updated.
							description = INCOMING | CHANGE;
							//description |= PSEUDO_CONFLICT;
						}
					}
				}
			}
		} else {
			if (!localExists) {
				if (getRemote() == null) {
					description = CONFLICTING | DELETION | PSEUDO_CONFLICT;
				} else {
					if (getComparator().compare(getBase(), getRemote())) {
						//description = OUTGOING | DELETION;
					} else {
						description = CONFLICTING | CHANGE;
					}
				}
			} else {
				//Local and Base exists...
				byte[] localBytes = Long.toString(CRCUtils.calculateCRC(
						new java.io.File(getLocal().getLocationURI()))).getBytes();

				if (getRemote() == null) {
					if (compareCRC(getLocal(), getBase(), localBytes))
						description = INCOMING | DELETION;
					else
						description = CONFLICTING | CHANGE;
				} else {
					//Local, Remote and Base exists...
					boolean ay = compareCRC(getLocal(), getBase(), localBytes);
					boolean am = getComparator().compare(getBase(), getRemote());
					if (ay && am) {
						// in-sync
					} else if (ay && !am) {
						//if (compareCRC(getLocal(), getBase())) {
							description = INCOMING | CHANGE;
						//} else {
						//	description = CONFLICTING | CHANGE;
						//}
					} else if (!ay && am) {
						//Force in sync
						//description = OUTGOING | CHANGE;
					} else {
						if(!compareCRC(getLocal(), getRemote(), localBytes)) {
							description = CONFLICTING | CHANGE;
						}
					}
				}
			}
		}
		
		return description;
		//return super.calculateKind();
	}
	
	private boolean compareCRC(IResource local, IResourceVariant variant, byte[] localSyncBytes) {
		//boolean result = true; //getComparator().compare(local, variant);
		//if (result) {
			if (local instanceof File) {
				return CRCUtils.equals(localSyncBytes, variant.asBytes());
			} else {
				return true; //result = true;
			}
		//}
		//return result;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.team.core.synchronize.SyncInfo#getBase()
	 */
	public IResourceVariant getBase() {
		// If the kind has been set and there is an incoming change
		// return null as the base since the server does not keep the
		// base contents
//		if ((getKind() & INCOMING) > 0) {
//			return null;
//		}
		return super.getBase();
	}
}
