/**
 * Copyright © 2012-2023 by Data Virtuality GmbH
 */
package org.teiid.translator.odata;

import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.odata4j.format.xml.EdmxFormatParser;
import org.odata4j.stax2.util.StaxUtil;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.language.Select;
import org.teiid.metadata.MetadataFactory;
import org.teiid.query.function.FunctionTree;
import org.teiid.query.function.UDFSource;
import org.teiid.query.metadata.MetadataValidator;
import org.teiid.query.metadata.SystemMetadata;
import org.teiid.query.metadata.TransformationMetadata;
import org.teiid.query.unittest.RealMetadataFactory;
import org.teiid.query.validator.ValidatorReport;
import org.teiid.translator.TranslatorException;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;

/**
 * @author Dmitry Pogorelov
 * @date 2023.08.21
 */
public class TestODataJoinColumnSQLVisitor {

	private ODataExecutionFactory translator;
	private TranslationUtility utility;

	@BeforeEach
	public void setUp() throws Exception {
		translator = new ODataExecutionFactory();
		translator.start();

		String csdl = ObjectConverterUtil.convertFileToString(UnitTestUtil.getTestDataFile("SFODataSet.xml"));
		ODataMetadataProcessor processor = new ODataMetadataProcessor();
		Properties props = new Properties();
		MetadataFactory mf = new MetadataFactory("vdb", 1, "SFODataSet", SystemMetadata.getInstance().getRuntimeTypeMap(), props, null);
		processor.getMetadata(mf, new EdmxFormatParser().parseMetadata(StaxUtil.newXMLEventReader(new InputStreamReader(new ByteArrayInputStream(csdl.getBytes())))));

		TransformationMetadata metadata = RealMetadataFactory.createTransformationMetadata(mf.asMetadataStore(), "SFODataSet", new FunctionTree("foo", new UDFSource(translator.getPushDownFunctions())));
		ValidatorReport report = new MetadataValidator().validate(metadata.getVdbMetaData(), metadata.getMetadataStore());
		if (report.hasItems()) {
			throw new RuntimeException(report.getFailureMessage());
		}
		utility = new TranslationUtility(metadata);
	}

	private ArrayList<TranslatorException> helpExecute(String query, String expected) throws Exception {
		Select cmd = (Select) this.utility.parseCommand(query);
		ODataSQLVisitor visitor = new ODataSQLVisitor(this.translator, utility.createRuntimeMetadata());
		visitor.visitNode(cmd);
		String actual = URLDecoder.decode(visitor.buildURL(), "UTF-8");
		assertEquals(expected, actual);
		return visitor.exceptions;
	}

	@Test
	public void testSelectSpecificColumns() throws Exception {
		List<TranslatorException> exceptions = helpExecute("SELECT externalCode FROM FOEventReason", "FOEventReason?$select=externalCode");
		assertTrue(exceptions.isEmpty());
	}
}
