package org.openlca.core.math.data_quality;

import java.util.HashMap;

import gnu.trove.map.hash.TIntObjectHashMap;
import org.openlca.core.database.IDatabase;
import org.openlca.core.database.NativeSql;
import org.openlca.core.matrix.IndexFlow;
import org.openlca.core.matrix.ProcessProduct;
import org.openlca.core.results.BaseResult;

class DQData2 {

	private final DQCalculationSetup setup;
	private final BaseResult result;

	private byte[][] processData;
	private BMatrix[] exchangeData;

	static DQData2 of(IDatabase db, DQCalculationSetup setup, BaseResult result) {
		var data = new DQData2(setup, result);
		data.load(db);
		return data;
	}

	private DQData2(DQCalculationSetup setup, BaseResult result) {
		this.setup = setup;
		this.result = result;
	}

	private void load(IDatabase db) {

		// load the process DQ data
		if (setup.processSystem != null) {
			var sql = "select id, f_dq_system, dq_entry " +
					"from tbl_processes";
			NativeSql.on(db).query(sql, r -> {
				long systemID = r.getLong(2);
				if (systemID != setup.processSystem.id)
					return true;


				var providers = result.techIndex.getProviders(r.getLong(1));
				if (providers.isEmpty())
					return true;

				return true;
			});
		}
	}

	/**
	 * Get the process data quality entry for the given product.
	 */
	public int[] get(ProcessProduct product) {
		if (processData == null)
			return null;
		int col = result.techIndex.getIndex(product);
		if (col < 0)
			return null;
		int[] values = new int[processData.length];
		for (int row = 0; row < processData.length; row++) {
			values[row] = processData[row][col];
		}
		return values;
	}

	/**
	 * Get the exchange data quality entry for the given product and flow.
	 */
	public int[] get(ProcessProduct product, IndexFlow flow) {
		if (exchangeData == null)
			return null;
		int row = result.flowIndex.of(flow);
		int col = result.techIndex.getIndex(product);
		if (row < 0 || col < 0)
			return null;
		int[] values = new int[exchangeData.length];
		for (int k = 0; k < exchangeData.length; k++) {
			values[k] = exchangeData[k].get(row, col);
		}
		return values;
	}

	private static class BMatrix {

		private final int columns;
		private final byte[] data;

		BMatrix(int rows, int columns) {
			this.columns = columns;
			this.data = new byte[rows * columns];
		}

		void set(int row, int col, int value) {
			data[index(row, col)] = (byte) value;
		}

		int get(int row, int col) {
			return data[index(row, col)];
		}

		int index(int row, int column) {
			return column + columns * row;
		}
	}
}

@@ -42,80 +42,8 @@
 y;%0A%0A
-import java.util.HashMap;%0A%0Aimport gnu.trove.map.hash.TIntObjectHashMap;%0A
 impo
@@ -787,24 +787,263 @@
 m != null) %7B
+%0A%0A%09%09%09var system = setup.processSystem;%0A%09%09%09var n = system.indicators.size();%0A%09%09%09processData = new byte%5Bn%5D%5B%5D;%0A%09%09%09for (int i = 0; i %3C n; i++) %7B%0A%09%09%09%09processData%5Bi%5D = new byte%5Bresult.techIndex.size()%5D;%0A%09%09%09%7D%0A%0A%09%09%09var techIndex = result.techIndex;
 %0A%09%09%09var sql 
@@ -1146,16 +1146,57 @@
 , r -%3E %7B
+%0A%0A%09%09%09%09// check that we have a valid entry
 %0A%09%09%09%09lon
@@ -1243,29 +1243,16 @@
 mID != s
-etup.processS
 ystem.id
@@ -1271,17 +1271,92 @@
 n true;%0A
-%0A
+%09%09%09%09var dqEntry = r.getString(3);%0A%09%09%09%09if (dqEntry == null)%0A%09%09%09%09%09return true;
 %0A%09%09%09%09var
@@ -1368,23 +1368,16 @@
 iders = 
-result.
 techInde
@@ -1454,16 +1454,367 @@
  true;%0A%0A
+%09%09%09%09// store the values of the entry%0A%09%09%09%09int%5B%5D values = system.toValues(dqEntry);%0A%09%09%09%09int _n = Math.min(n, values.length);%0A%09%09%09%09for (int i = 0; i %3C _n; i++) %7B%0A%09%09%09%09%09byte%5B%5D data = processData%5Bi%5D;%0A%09%09%09%09%09byte value = (byte) values%5Bi%5D;%0A%09%09%09%09%09for (var provider : providers) %7B%0A%09%09%09%09%09%09int col = techIndex.getIndex(provider);%0A%09%09%09%09%09%09data%5Bcol%5D = value;%0A%09%09%09%09%09%7D%0A%09%09%09%09%7D%0A
 %09%09%09%09retu
@@ -1833,24 +1833,25 @@
 %7D);%0A%09%09%7D%0A%09%7D%0A%0A
+%0A
 %09/**%0A%09 * Get

store process values in an array of