/*
 * Copyright 2023 epimethix@protonmail.com
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.github.epimethix.lumicore.common.orm;

import java.sql.SQLException;
import java.util.List;

import com.github.epimethix.lumicore.common.orm.model.Entity;
import com.github.epimethix.lumicore.common.orm.model.ManyToManyEntity;
import com.github.epimethix.lumicore.properties.LumicoreProperties;

public interface ManyToManyRepository<E extends ManyToManyEntity<A, B>, A extends Entity<?>, B extends Entity<?>>
		extends Repository<E, Long> {
	default List<B> listByA(Entity<?> a) throws SQLException {
		return listByA(a, getDB().getActiveUser(), LumicoreProperties.CLOSE_CONNECTION_AFTER_OPERATION);
	}

	default List<B> listByA(Entity<?> a, boolean closeConnection) throws SQLException {
		return listByA(a, getDB().getActiveUser(), closeConnection);
	}

	List<B> listByA(Entity<?> a, String user, boolean closeConnection) throws SQLException;

	default List<A> listByB(Entity<?> b) throws SQLException {
		return listByB(b, getDB().getActiveUser(), LumicoreProperties.CLOSE_CONNECTION_AFTER_OPERATION);
	}

	default List<A> listByB(Entity<?> b, boolean closeConnection) throws SQLException {
		return listByB(b, getDB().getActiveUser(), closeConnection);
	}

	List<A> listByB(Entity<?> b, String user, boolean closeConnection) throws SQLException;

	default void saveByA(Entity<?> a, List<? extends Entity<?>> bs, boolean closeConnection)
			throws SQLException {
		saveByA(a, bs, getDB().getActiveUser(), closeConnection);
	}

	default void saveByA(Entity<?> a, List<? extends Entity<?>> bs) throws SQLException {
		saveByA(a, bs, getDB().getActiveUser(), LumicoreProperties.CLOSE_CONNECTION_AFTER_OPERATION);
	}

	void saveByA(Entity<?> a, List<? extends Entity<?>> bs, String user, boolean closeConnection)
			throws SQLException;

	default void saveByB(Entity<?> b, List<? extends Entity<?>> as, boolean closeConnection)
			throws SQLException {
		saveByB(b, as, getDB().getActiveUser(), closeConnection);
	}

	default void saveByB(Entity<?> b, List<? extends Entity<?>> as) throws SQLException {
		saveByB(b, as, getDB().getActiveUser(), LumicoreProperties.CLOSE_CONNECTION_AFTER_OPERATION);
	}

	void saveByB(Entity<?> b, List<? extends Entity<?>> as, String user, boolean closeConnection)
			throws SQLException;

	E saveDirect(Entity<?> o) throws SQLException;

	Class<?> getClassA();

	Class<?> getTypeA();

	String getFieldNameA();

	Class<?> getClassB();

	Class<?> getTypeB();

	String getFieldNameB();
}
