//Gruppe 01 (Übung 2)
//Aufgabe 2-1

package uebung02.aufgabe01;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;

/**
* Vergleicht zwei Ressourcen im Netz auf Übereinstimmung.
* Zunächst werden die Inhalts-Header, danach die Ressourcen
* selbst verglichen.
* 
* @author Tilman Walther
*/
public class NetComparator {
	
	// Header, die auf Unterschiede im Inhalt schließen lassen
	private static String[] header = new String[] {
			"Content-Type",
			"Content-Length",
			"Content-Encoding",
			"Content-Language",
			"Last-Modified",
			"Expires" };
		
	/**
	 * Compares two resources given as URLs.
	 * 
	 * @param s1 The URL for the first resource
	 * @param s2 The URL for the second resource
	 * @return true, if the resources are equal, false otherwise
	 * @throws IOException if an I/O Error occurs
	 */
	public static boolean compare(String s1, String s2) throws IOException {
		
		// Verbindungen für die Ressourcen erstellen
		
		URL url1 = new URL(s1);
		URLConnection connection1 = url1.openConnection();
		
		URL url2 = new URL(s2);
		URLConnection connection2 = url2.openConnection();
		
		
		// Header vergleichen
		
		String val1; // Header-Value Resource 1
		String val2; // Header-Value Resource 2
		
		long differences = 0;  // Anz. festegestellter Unterschiede
		
		// relevante Header durchgehen
		for (int i = 0; i < header.length; i++) {
			val1 = connection1.getHeaderField(header[i]);
			val2 = connection2.getHeaderField(header[i]);
			
			if ((val1 != null) && (val2 != null)) {
				
				if (!val1.equals(val2)) {
					System.out.println("Header verschieden: "+header[i]+" "+val1+" / "+val2);
					differences++;
				}	
			}
		}
				
		
		// Inhalt vergleichen
		
		BufferedInputStream input1 = new BufferedInputStream(connection1.getInputStream());
		BufferedInputStream input2 = new BufferedInputStream(connection2.getInputStream());
		
		long lengthRead = 0;
		long bytesDifferent = 0;
		long areasDifferent = 0;
		
		int length1 = 0;
		int length2 = 0;
		byte[] buffer1 = new byte[1024];
		byte[] buffer2 = new byte[1024];
		
		boolean differentArea = false;
		long marker = 0;
		
		// Inhalt vergleichen
		do {
			
			length1 = input1.read(buffer1);
			length2 = input2.read(buffer2);
			
			int in1 = Math.min(length1, length2);
			
			// Unterschiedliche Bereiche suchen
			for (int i = 0; i < in1; i++) {
				
				if ((buffer1[i] != buffer2[i])) {
					if (!differentArea) {							
						differentArea = true;
						marker = lengthRead+i;
					}
				}
				else if (differentArea) {
					differentArea = false;
					bytesDifferent += (lengthRead + i - marker);
					
					System.out.println("Bereich von "+marker+" bis "+(lengthRead + i-1)+" unterschiedlich");
					areasDifferent++;
					differences++;
				}
				
			}
			
			lengthRead += length1;
			
		} while ((length1 > 0) && (length1 == length2));
		
		
		// Überprüfen, ob aus beiden Streams gleich viel gelesen wurde, bzw.
		// ob ein Stream noch nicht am Ende angelangt ist
		long diffLength = Math.abs(input1.available()+length1-input2.available()-length2);
		
		if (diffLength > 0) {
			System.out.println("Länge unterschiedlich ("+diffLength+" Byte)");
			differences++;
		}
		
		
		// Endergebnis ausgeben
		if (differences > 0) {
			System.out.println("Test beendet, "+differences+" Unterschiede festgestellt.\nDer Inhalt unterscheidet sich in "+bytesDifferent+" Bytes in "+areasDifferent+" Bereichen.");
			return false;
		}
		
		System.out.println("Test beendet, Ressourcen stimmen überein.");
		return true;
	}
	
	public static void main(String[] args) throws IOException {
		
		if (args.length == 2) {
			NetComparator.compare(args[0], args[1]);
		}
		else if (args.length == 0) {
			
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
			
			System.out.print("Please insert first URL: ");
			String s1 = in.readLine();
			
			System.out.print("Please insert second URL: ");
			String s2 = in.readLine();
			
			NetComparator.compare(s1, s2);
		}
		else {
			System.out.println("Aufruf: NetCompare [url1 url2]");
		}
	}
}
