/*******************************************************************************
 * Copyright (c) 2004, 2020 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tools.internal;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

public abstract class JNIGenerator implements Flags {

	JNIClass mainClass;
	JNIClass[] classes;
	MetaData metaData;
	String delimiter;
	PrintStream output;
	ProgressMonitor progress;
	

public JNIGenerator() {
	delimiter = System.lineSeparator();
	output = System.out;
	metaData = new MetaData(new Properties());
}

public static String skipCopyrights(InputStream is) throws IOException {
	int state = 0;
	StringBuilder copyrights = new StringBuilder();
	while (state != 5) {
		int c = is.read();
		if (c == -1) return null;
		switch (state) {
			case 0:
				if (!Character.isWhitespace((char)c)) state = 1;
			case 1:
				if (c == '/') state = 2;
				else return null;
				break;
			case 2:
				if (c == '*') state = 3;
				else return null;
				break;
			case 3:
				if (c == '*') state = 4;
				break;
			case 4:
				if (c == '/') state = 5;
				else state = 3;
				break;
		}
		if (state > 0) copyrights.append((char)c);
	}
	return copyrights.toString();
}

public static boolean compare(InputStream is1, InputStream is2) throws IOException {
	skipCopyrights(is1);
	skipCopyrights(is2);
	while (true) {
		int c1 = is1.read();
		int c2 = is2.read();
		if (c1 != c2) return false;
		if (c1 == -1) break;
	}
	return true;
}

public static void output(byte[] bytes, String fileName) throws IOException {
	try (FileInputStream is = new FileInputStream(fileName)){
		if (compare(new ByteArrayInputStream(bytes), new BufferedInputStream(is))) return;
	} catch (FileNotFoundException e) {
	}
	try (FileOutputStream out = new FileOutputStream(fileName)) {
		out.write(bytes);
	}
}

public static String getDelimiter(String fileName) {
	
	try (InputStream is = new BufferedInputStream(new FileInputStream(fileName))){
		int c;
		while ((c = is.read()) != -1) {
			if (c == '\n') return "\n";
			if (c == '\r') {
				int c1 = is.read();
				if (c1 == '\n') {
					return "\r\n";
				}
				return "\r";
			}
		}
	} catch (IOException e) {
	}
	return System.lineSeparator();
}

String fixDelimiter(String str) {
	if (delimiter.equals("\n")) return str;
	int index = 0, length = str.length();
	StringBuilder buffer = new StringBuilder();
	while (index != -1) {
		int start = index;
		index = str.indexOf('\n', start);
		if (index == -1) {
			buffer.append(str.substring(start, length));
		} else {
			buffer.append(str.substring(start, index));
			buffer.append(delimiter);
			index++;
		}
	}
	return buffer.toString();
}

static String getFunctionName(JNIMethod method) {
	return getFunctionName(method, method.getParameterTypes());
}

static String getFunctionName(JNIMethod method, JNIType[] paramTypes) {
	if ((method.getModifiers() & Modifier.NATIVE) == 0) return method.getName();
	String function = toC(method.getName());
	if (!method.isNativeUnique()) {
		StringBuilder buffer = new StringBuilder();
		buffer.append(function);
		buffer.append("__");
		for (JNIType paramType : paramTypes) {
			buffer.append(toC(paramType.getTypeSignature()));
		}
		return buffer.toString();
	}
	return function;
}

static String loadFile (String file) {
	try (FileReader fr = new FileReader(file);
		BufferedReader br = new BufferedReader(fr)){
		StringBuilder str = new StringBuilder();
		char[] buffer = new char[1024];
		int read;
		while ((read = br.read(buffer)) != -1) {
			str.append(buffer, 0, read);
		}
		fr.close();
		return str.toString();
	} catch (IOException e) {
		throw new RuntimeException("File not found:" + file, e);
	}
}

static void sort(JNIMethod[] methods) {
	Arrays.sort(methods, (mth1, mth2) -> {
		int result = mth1.getName().compareTo(mth2.getName());
		return result != 0 ? result : getFunctionName(mth1).compareTo(getFunctionName(mth2));
	});
}

static void sort(JNIField[] fields) {
	Arrays.sort(fields, (a, b) -> a.getName().compareTo(b.getName()));
}

static void sort(JNIClass[] classes) {
	Arrays.sort(classes, (a, b) -> a.getName().compareTo(b.getName()));	
}

static String[] split(String str, String separator) {
	StringTokenizer tk = new StringTokenizer(str, separator);
	List<String> result = new ArrayList<>();
	while (tk.hasMoreTokens()) {
		result.add(tk.nextToken());
	}
	return result.toArray(new String[result.size()]);
}

static String toC(String str) {
	int length = str.length();
	StringBuilder buffer = new StringBuilder(length * 2);
	for (int i = 0; i < length; i++) {
		char c = str.charAt(i);
		switch (c) {
			case '_': buffer.append("_1"); break;
			case ';': buffer.append("_2"); break;
			case '[': buffer.append("_3"); break;
			case '.': buffer.append("_"); break;
			case '/': buffer.append("_"); break;
			default: buffer.append(c);
		}
	}
	return buffer.toString();
}

public abstract void generate(JNIClass clazz);

public void generateCopyright() {
}

public void generateAutoGenNote() {
	outputln("/* Note: This file was auto-generated by " + JNIGenerator.class.getName() + " */");
	outputln("/* DO NOT EDIT - your changes will be lost. */");
	outputln();
}

public void generateIncludes() {
}

public void generate() {
	if (classes == null) return;
	generateCopyright();
	generateAutoGenNote();
	generateIncludes();
	sort(classes);
	for (JNIClass clazz : classes) {
		if (getGenerate(clazz)) generate(clazz);
		if (progress != null) progress.step();
	}
	output.flush();
}

public void generateMetaData(String key) {
	MetaData mt = getMetaData();
	String data = mt.getMetaData(key, null);
	if (data == null) return;
	if (data.length() == 0) return;
	outputln(fixDelimiter(data));
}

public JNIClass[] getClasses() {
	return classes;
}

public boolean getCPP() {
	for (JNIClass clazz : classes) {
		if (clazz.getFlag(FLAG_CPP)) {
			return true;
		}
	}
	return false;
}

public String getDelimiter() {
	return delimiter;
}

public String getExtension() {
	return getCPP() ? ".cpp" : getM() ? ".m" : ".c";
}

public String getFileName() {
	return getOutputName() + getSuffix() + getExtension();
}

protected boolean getGenerate(JNIItem item) {
	return item.getGenerate();
}

public PrintStream getOutput() {
	return output;
}

public String getOutputName() {
	return getMainClass().getSimpleName().toLowerCase();
}

public boolean getM() {
	for (JNIClass clazz : classes) {
		if (clazz.getFlag(FLAG_M)) {
			return true;
		}
	}
	return false;
}

public JNIClass getMainClass() {
	return mainClass;
}

public MetaData getMetaData() {
	return metaData;
}

public ProgressMonitor getProgressMonitor() {
	return progress;
}

public String getSuffix() {
	return "";
}

public void output(String str) {
	output.print(str);
}

public void outputln() {
	output(getDelimiter());
}

public void outputln(String str) {
	output(str);
	output(getDelimiter());
}

public void setClasses(JNIClass[] classes) {
	this.classes = classes;
}

public void setDelimiter(String delimiter) {
	this.delimiter = delimiter;
}

public void setMainClass(JNIClass mainClass) {
	this.mainClass = mainClass;
}

public void setMetaData(MetaData data) {
	metaData = data;
}

public void setOutput(PrintStream output) {
	this.output = output;
}

public void setProgressMonitor(ProgressMonitor progress) {
	this.progress = progress;
}

}
