package clientP2P;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;
import java.io.IOException;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
import java.nio.file.StandardCopyOption;
import localException.ProtocolError;
import localException.InternalError;
import localException.TransmissionError;
import localException.SizeError;
import localException.VersionError;
import remoteException.EmptyDirectory;
import remoteException.EmptyFile;
import remoteException.VersionRemoteError;
import remoteException.ProtocolRemoteError;
import remoteException.NotFound;
import remoteException.InternalRemoteError;
import remoteException.NotATracker;
import protocolP2P.HashAlgorithm;
import protocolP2P.HashResponse;
import protocolP2P.HashRequest;
import protocolP2P.ProtocolP2PPacketUDP;
import protocolP2P.ProtocolP2PPacket;
import protocolP2P.Payload;
import protocolP2P.FilePart;
import protocolP2P.LoadRequest;
import clientP2P.ClientDownloadPartUDP;
import clientP2P.ClientDownload;
import tools.HostItem;
import tools.Logger;
import tools.LogLevel;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.io.IOException;


/** Class to download file from udp
* @author	Louis Royer
* @author	Flavien Haas
* @author	JS Auge
* @version	1.0
*/
public class ClientDownloadUDP extends ClientDownload {

	/** Constructor with parameters: filename, list of hosts, parts subdirectory and dirStorage
	 * @param filename	name of file to download
	 * @param hostList	list of servers
	 * @param partsSubdir	directory to store .part files
	 * @param dirStorage	directory to write assembled file
	 * @param logger	Logger
	 * @param client	HostItem of the application
	 * @param tracker	HostItem of the tracker
	 */
	public ClientDownloadUDP(String filename, List<HostItem> hostList, String partsSubdir, String dirStorage, Logger logger, HostItem client, HostItem tracker) {
		super(filename, hostList, partsSubdir, dirStorage, logger, client, tracker);
	}

	/** Create a clientDownloadPart
	 * @param hostItem	Hostitem of the server
	 */
	protected ClientDownloadPart createDownloadPart(HostItem hostItem) {
		return (ClientDownloadPart)new ClientDownloadPartUDP((ClientDownload)this, filename, hostItem.getUDPSocket(), partsSubdir, logger, client, tracker);
	}

	/** Implementation of writeLog
	 * @param text	Text to log
	 * @param logLevel	level of logging
	 */
	protected void writeLog(String text, LogLevel logLevel) {
		logger.writeUDP(text, logLevel);
	}

	/** Implementation of writeLog
	 * @param e	exception to log
	 * @param logLevel	level of logging
	 */
	protected void writeLog(Exception e, LogLevel logLevel) {
		logger.writeUDP(e, logLevel);
	}

	/** Create packets
	 * @param payload	Payload
	 */
	protected < T extends Payload > ProtocolP2PPacket<T> createProtocolP2PPacket(T payload) {
		return (ProtocolP2PPacket<T>)new ProtocolP2PPacketUDP<T>(payload);
	}

	/** Getter for HostItem socket
	 * @param hostItem	HostItemç
	 * @throws	SocketException
	 * @throws	UnknownHostException
	 * @throws	IOException
	 */
	protected Object getHostItemSocket(HostItem hostItem) throws SocketException, UnknownHostException, IOException {
		return (Object)hostItem.tryGetUDPSocket();
	}

	/** Close HostItem socket
	 * @param hostItem	HostItem
	 */
	protected void closeHostItemSocket(HostItem hostItem) {
		hostItem.closeUDPSocket();
	}
}
