/*******************************************************************************
 * Copyright (c) 2004, 2016 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.core.internal.registry;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.Map.Entry;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.spi.RegistryContributor;

public class TableWriter {
	private static final byte fileError = 0;

	File mainDataFile;
	File extraDataFile;
	File tableFile;
	File contributionsFile;
	File contributorsFile;
	File namespacesFile;
	File orphansFile;

	void setMainDataFile(File main) {
		mainDataFile = main;
	}

	void setExtraDataFile(File extra) {
		extraDataFile = extra;
	}

	void setTableFile(File table) {
		tableFile = table;
	}

	void setContributionsFile(File fileName) {
		contributionsFile = fileName;
	}

	void setContributorsFile(File fileName) {
		contributorsFile = fileName;
	}

	void setNamespacesFile(File fileName) {
		namespacesFile = fileName;
	}

	void setOrphansFile(File orphan) {
		orphansFile = orphan;
	}

	DataOutputStream mainOutput;
	DataOutputStream extraOutput;
	FileOutputStream mainFileOutput = null;
	FileOutputStream extraFileOutput = null;

	private OffsetTable offsets;

	private final ExtensionRegistry registry;
	private RegistryObjectManager objectManager;

	public TableWriter(ExtensionRegistry registry) {
		this.registry = registry;
	}

	private int getExtraDataPosition() {
		return extraOutput.size();
	}

	public boolean saveCache(RegistryObjectManager objectManager, long timestamp) {
		this.objectManager = objectManager;
		try {
			if (!openFiles())
				return false;
			try {
				saveExtensionRegistry(timestamp);
			} catch (IOException io) {
				log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, io));
				return false;
			}
		} finally {
			closeFiles();
		}
		return true;
	}

	private boolean openFiles() {
		try {
			mainFileOutput = new FileOutputStream(mainDataFile);
			mainOutput = new DataOutputStream(new BufferedOutputStream(mainFileOutput));
			extraFileOutput = new FileOutputStream(extraDataFile);
			extraOutput = new DataOutputStream(new BufferedOutputStream(extraFileOutput));
		} catch (FileNotFoundException e) {
			if (mainFileOutput != null)
				try {
					mainFileOutput.close();
				} catch (IOException e1) {
					//Ignore
				}

			log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_unableToCreateCache, e));
			return false;
		}
		return true;
	}

	private void closeFiles() {
		try {
			if (mainOutput != null) {
				mainOutput.flush();
				if (mainFileOutput.getFD().valid()) {
					mainFileOutput.getFD().sync();
				}
				mainOutput.close();
			}
		} catch (IOException e) {
			log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e));
			e.printStackTrace();
		}
		try {
			if (extraOutput != null) {
				extraOutput.flush();
				if (extraFileOutput.getFD().valid()) {
					extraFileOutput.getFD().sync();
				}
				extraOutput.close();
			}
		} catch (IOException e) {
			log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, fileError, RegistryMessages.meta_registryCacheWriteProblems, e));
			e.printStackTrace();
		}
	}

	private void saveExtensionRegistry(long timestamp) throws IOException {
		ExtensionPointHandle[] points = objectManager.getExtensionPointsHandles();
		offsets = new OffsetTable(objectManager.getNextId());
		for (ExtensionPointHandle point : points) {
			saveExtensionPoint(point);
		}
		saveOrphans();
		saveContributions(objectManager.getContributions());
		saveContributors(objectManager.getContributors());
		saveNamespaces(objectManager.getNamespacesIndex());
		closeFiles(); //Close the files here so we can write the appropriate size information in the table file.
		saveTables(timestamp); //Write the table last so if that is something went wrong we can know
	}

	private void saveContributions(KeyedHashSet[] contributions) throws IOException {
		FileOutputStream fosNamespace = new FileOutputStream(contributionsFile);
		DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace));
		KeyedElement[] newElements = contributions[0].elements();
		KeyedElement[] formerElements = contributions[1].elements();

		// get count of contributions that will be cached
		int cacheSize = 0;
		for (KeyedElement newElement : newElements) {
			if (((Contribution) newElement).shouldPersist()) {
				cacheSize++;
			}
		}
		for (KeyedElement formerElement : formerElements) {
			if (((Contribution) formerElement).shouldPersist()) {
				cacheSize++;
			}
		}
		outputNamespace.writeInt(cacheSize);

		for (KeyedElement newElement : newElements) {
			Contribution element = (Contribution) newElement;
			if (element.shouldPersist()) {
				writeStringOrNull(element.getContributorId(), outputNamespace);
				saveArray(filterContributionChildren(element), outputNamespace);
			}
		}
		for (KeyedElement formerElement : formerElements) {
			Contribution element = (Contribution) formerElement;
			if (element.shouldPersist()) {
				writeStringOrNull(element.getContributorId(), outputNamespace);
				saveArray(filterContributionChildren(element), outputNamespace);
			}
		}
		outputNamespace.flush();
		fosNamespace.getFD().sync();
		outputNamespace.close();
	}

	// Contribution has raw children in a unique format that combines extensions and extension points.
	// To filter, need to dis-assmeble, filter, and then re-assemble its raw children
	private int[] filterContributionChildren(Contribution element) {
		int[] extensionPoints = filter(element.getExtensionPoints());
		int[] extensions = filter(element.getExtensions());
		int[] filteredRawChildren = new int[2 + extensionPoints.length + extensions.length];
		System.arraycopy(extensionPoints, 0, filteredRawChildren, 2, extensionPoints.length);
		System.arraycopy(extensions, 0, filteredRawChildren, 2 + extensionPoints.length, extensions.length);
		filteredRawChildren[Contribution.EXTENSION_POINT] = extensionPoints.length;
		filteredRawChildren[Contribution.EXTENSION] = extensions.length;
		return filteredRawChildren;
	}

	private void saveNamespaces(KeyedHashSet namespacesIndex) throws IOException {
		FileOutputStream fosNamespace = new FileOutputStream(namespacesFile);
		DataOutputStream outputNamespace = new DataOutputStream(new BufferedOutputStream(fosNamespace));
		KeyedElement[] elements = namespacesIndex.elements();

		KeyedElement[] cachedElements = new KeyedElement[elements.length];
		int cacheSize = 0;
		for (KeyedElement e : elements) {
			RegistryIndexElement element = (RegistryIndexElement) e;
			int[] extensionPoints = filter(element.getExtensionPoints());
			int[] extensions = filter(element.getExtensions());
			if (extensionPoints.length == 0 && extensions.length == 0)
				continue;
			RegistryIndexElement cachedElement = new RegistryIndexElement((String) element.getKey(), extensionPoints, extensions);
			cachedElements[cacheSize] = cachedElement;
			cacheSize++;
		}

		outputNamespace.writeInt(cacheSize);
		for (int i = 0; i < cacheSize; i++) {
			RegistryIndexElement element = (RegistryIndexElement) cachedElements[i];
			writeStringOrNull((String) element.getKey(), outputNamespace);
			saveArray(element.getExtensionPoints(), outputNamespace); // it was pre-filtered as we counted the number of elements
			saveArray(element.getExtensions(), outputNamespace); // it was pre-filtered as we counted the number of elements
		}
		outputNamespace.flush();
		fosNamespace.getFD().sync();
		outputNamespace.close();
	}

	private void saveContributors(HashMap<?, ?> contributors) throws IOException {
		FileOutputStream fosContributors = new FileOutputStream(contributorsFile);
		DataOutputStream outputContributors = new DataOutputStream(new BufferedOutputStream(fosContributors));

		Collection<?> entries = contributors.values();
		outputContributors.writeInt(entries.size());

		for (Object entry : entries) {
			RegistryContributor contributor = (RegistryContributor) entry;
			writeStringOrNull(contributor.getActualId(), outputContributors);
			writeStringOrNull(contributor.getActualName(), outputContributors);
			writeStringOrNull(contributor.getId(), outputContributors);
			writeStringOrNull(contributor.getName(), outputContributors);
		}

		outputContributors.flush();
		fosContributors.getFD().sync();
		outputContributors.close();
	}

	private void saveTables(long registryTimeStamp) throws IOException {
		FileOutputStream fosTable = new FileOutputStream(tableFile);
		DataOutputStream outputTable = new DataOutputStream(new BufferedOutputStream(fosTable));
		writeCacheHeader(outputTable, registryTimeStamp);
		outputTable.writeInt(objectManager.getNextId());
		offsets.save(outputTable);
		objectManager.getExtensionPoints().save(outputTable, objectManager); // uses writer to filter contents
		outputTable.flush();
		fosTable.getFD().sync();
		outputTable.close();
	}

	private void writeCacheHeader(DataOutputStream output, long registryTimeStamp) throws IOException {
		output.writeInt(TableReader.CACHE_VERSION);
		output.writeLong(registry.computeState());
		output.writeLong(registryTimeStamp);
		output.writeLong(mainDataFile.length());
		output.writeLong(extraDataFile.length());
		output.writeLong(contributionsFile.length());
		output.writeLong(contributorsFile.length());
		output.writeLong(namespacesFile.length());
		output.writeLong(orphansFile.length());
		output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_OS, RegistryProperties.empty));
		output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_WS, RegistryProperties.empty));
		output.writeUTF(RegistryProperties.getProperty(IRegistryConstants.PROP_NL, RegistryProperties.empty));
		output.writeBoolean(registry.isMultiLanguage());
	}

	private void saveArray(int[] array, DataOutputStream out) throws IOException {
		if (array == null) {
			out.writeInt(0);
			return;
		}
		out.writeInt(array.length);
		for (int element : array) {
			out.writeInt(element);
		}
	}

	private void saveExtensionPoint(ExtensionPointHandle xpt) throws IOException {
		if (!xpt.shouldPersist())
			return;
		//save the file position
		offsets.put(xpt.getId(), mainOutput.size());
		//save the extensionPoint
		mainOutput.writeInt(xpt.getId());
		saveArray(filter(xpt.getObject().getRawChildren()), mainOutput);
		mainOutput.writeInt(getExtraDataPosition());
		saveExtensionPointData(xpt);

		saveExtensions(xpt.getExtensions(), mainOutput);
	}

	private void saveExtension(ExtensionHandle ext, DataOutputStream outputStream) throws IOException {
		if (!ext.shouldPersist())
			return;
		offsets.put(ext.getId(), outputStream.size());
		outputStream.writeInt(ext.getId());
		writeStringOrNull(ext.getSimpleIdentifier(), outputStream);
		writeStringOrNull(ext.getNamespaceIdentifier(), outputStream);
		saveArray(filter(ext.getObject().getRawChildren()), outputStream);
		outputStream.writeInt(getExtraDataPosition());
		saveExtensionData(ext);
	}

	private void writeStringArray(String[] array, DataOutputStream outputStream) throws IOException {
		outputStream.writeInt(array == null ? 0 : array.length);
		for (int i = 0; i < (array == null ? 0 : array.length); i++) {
			writeStringOrNull(array[i], outputStream);
		}
	}

	private void writeStringArray(String[] array, int size, DataOutputStream outputStream) throws IOException {
		outputStream.writeInt(array == null ? 0 : size);
		if (array == null)
			return;
		for (int i = 0; i < size; i++) {
			writeStringOrNull(array[i], outputStream);
		}
	}

	//Save Configuration elements depth first
	private void saveConfigurationElement(ConfigurationElementHandle element, DataOutputStream outputStream, DataOutputStream extraOutputStream, int depth) throws IOException {
		if (!element.shouldPersist())
			return;
		DataOutputStream currentOutput = outputStream;
		if (depth > 2)
			currentOutput = extraOutputStream;

		offsets.put(element.getId(), currentOutput.size());

		currentOutput.writeInt(element.getId());
		ConfigurationElement actualCe = (ConfigurationElement) element.getObject();

		writeStringOrNull(actualCe.getContributorId(), currentOutput);
		writeStringOrNull(actualCe.getName(), currentOutput);
		currentOutput.writeInt(actualCe.parentId);
		currentOutput.writeByte(actualCe.parentType);
		currentOutput.writeInt(depth > 1 ? extraOutputStream.size() : -1);
		writeStringArray(actualCe.getPropertiesAndValue(), currentOutput);
		//save the children
		saveArray(filter(actualCe.getRawChildren()), currentOutput);

		if (actualCe instanceof ConfigurationElementMulti) {
			ConfigurationElementMulti multiCE = (ConfigurationElementMulti) actualCe;
			int NLs = multiCE.getNumCachedLocales();
			currentOutput.writeInt(NLs);
			if (NLs != 0) {
				writeStringArray(multiCE.getCachedLocales(), NLs, currentOutput);
				String[][] translated = multiCE.getCachedTranslations();
				for (int i = 0; i < NLs; i++) {
					writeStringArray(translated[i], currentOutput);
				}
			}
		}

		ConfigurationElementHandle[] childrenCEs = (ConfigurationElementHandle[]) element.getChildren();
		for (ConfigurationElementHandle childrenCE : childrenCEs) {
			saveConfigurationElement(childrenCE, outputStream, extraOutputStream, depth + 1);
		}

	}

	private void saveExtensions(IExtension[] exts, DataOutputStream outputStream) throws IOException {
		for (IExtension ext : exts) {
			saveExtension((ExtensionHandle) ext, outputStream);
		}
		for (IExtension ext : exts) {
			if (!((ExtensionHandle) ext).shouldPersist()) {
				continue;
			}
			IConfigurationElement[] ces = ext.getConfigurationElements();
			int countCElements = 0;
			boolean[] save = new boolean[ces.length];
			for (int j = 0; j < ces.length; j++) {
				if (((ConfigurationElementHandle) ces[j]).shouldPersist()) {
					save[j] = true;
					countCElements++;
				} else
					save[j] = false;
			}
			outputStream.writeInt(countCElements);
			for (int j = 0; j < ces.length; j++) {
				if (save[j])
					saveConfigurationElement((ConfigurationElementHandle) ces[j], outputStream, extraOutput, 1);
			}
		}
	}

	private void saveExtensionPointData(ExtensionPointHandle xpt) throws IOException {
		writeStringOrNull(xpt.getLabelAsIs(), extraOutput);
		writeStringOrNull(xpt.getSchemaReference(), extraOutput);
		writeStringOrNull(xpt.getUniqueIdentifier(), extraOutput);
		writeStringOrNull(xpt.getNamespaceIdentifier(), extraOutput);
		writeStringOrNull(((ExtensionPoint) xpt.getObject()).getContributorId(), extraOutput);
	}

	private void saveExtensionData(ExtensionHandle extension) throws IOException {
		writeStringOrNull(extension.getLabelAsIs(), extraOutput);
		writeStringOrNull(extension.getExtensionPointUniqueIdentifier(), extraOutput);
		writeStringOrNull(extension.getContributorId(), extraOutput);
	}

	private void writeStringOrNull(String string, DataOutputStream out) throws IOException {
		if (string == null)
			out.writeByte(TableReader.NULL);
		else {
			byte[] data = string.getBytes(StandardCharsets.UTF_8);
			if (data.length > 65535) {
				out.writeByte(TableReader.LOBJECT);
				out.writeInt(data.length);
				out.write(data);
			} else {
				out.writeByte(TableReader.OBJECT);
				out.writeUTF(string);
			}
		}
	}

	private void saveOrphans() throws IOException {
		Map<String, int[]> orphans = objectManager.getOrphanExtensions();
		Map<String, int[]> filteredOrphans = new HashMap<>();
		for (Entry<String, int[]> entry : orphans.entrySet()) {
			int[] filteredValue = filter(entry.getValue());
			if (filteredValue.length != 0)
				filteredOrphans.put(entry.getKey(), filteredValue);
		}
		FileOutputStream fosOrphan = new FileOutputStream(orphansFile);
		DataOutputStream outputOrphan = new DataOutputStream(new BufferedOutputStream(fosOrphan));
		outputOrphan.writeInt(filteredOrphans.size());
		Set<Entry<String, int[]>> elements = filteredOrphans.entrySet();
		for (Entry<String, int[]> entry : elements) {
			outputOrphan.writeUTF(entry.getKey());
			saveArray(entry.getValue(), outputOrphan);
		}
		for (Entry<String, int[]> entry : elements) {
			mainOutput.writeInt(entry.getValue().length);
			saveExtensions((IExtension[]) objectManager.getHandles(entry.getValue(), RegistryObjectManager.EXTENSION), mainOutput);
		}
		outputOrphan.flush();
		fosOrphan.getFD().sync();
		outputOrphan.close();
	}

	private void log(Status status) {
		registry.log(status);
	}

	// Filters out registry objects that should not be cached
	private int[] filter(int[] input) {
		boolean[] save = new boolean[input.length];
		int resultSize = 0;
		for (int i = 0; i < input.length; i++) {
			if (objectManager.shouldPersist(input[i])) {
				save[i] = true;
				resultSize++;
			} else
				save[i] = false;
		}
		int[] result = new int[resultSize];
		int pos = 0;
		for (int i = 0; i < input.length; i++) {
			if (save[i]) {
				result[pos] = input[i];
				pos++;
			}
		}
		return result;
	}
}
