/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     dclarke - Dynamic Persistence
//       http://wiki.eclipse.org/EclipseLink/Development/Dynamic
//       (https://bugs.eclipse.org/bugs/show_bug.cgi?id=200045)
//     mnorman - tweaks to work from Ant command-line,
//               get database properties from System, etc.
//
package org.eclipse.persistence.testing.tests.dynamic.simple.sequencing;

//JUnit4 imports
import org.junit.Test;

//EclipseLink imports
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.dynamic.DynamicEntity;
import org.eclipse.persistence.dynamic.DynamicHelper;
import org.eclipse.persistence.dynamic.DynamicType;
import org.eclipse.persistence.exceptions.DatabaseException;
import org.eclipse.persistence.expressions.ExpressionBuilder;
import org.eclipse.persistence.sessions.IdentityMapAccessor;
import org.eclipse.persistence.queries.ReadObjectQuery;
import org.eclipse.persistence.queries.ReportQuery;
import org.eclipse.persistence.sessions.DatabaseSession;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.UnitOfWork;

import static org.junit.Assert.*;

//domain-specific (testing) imports

public abstract class BaseSequencingTestSuite  {

    public static final String TABLE_NAME = "SIMPLE_TABLE_SEQ";
    public static final String SEQ_TABLE_NAME = "TEST_SEQ";
    public static final String ENTITY_TYPE = "Simple";

    //test fixtures
    static DatabaseSession session = null;
    static DynamicHelper dynamicHelper = null;

    @Test
    public void verifyConfig() throws Exception {
        ClassDescriptor descriptor = dynamicHelper.getSession().getClassDescriptorForAlias(ENTITY_TYPE);
        assertNotNull("No descriptor found for alias: " + ENTITY_TYPE, descriptor);

        DynamicType simpleType = dynamicHelper.getType(ENTITY_TYPE);
        assertNotNull("EntityType not found for alias: " + ENTITY_TYPE, simpleType);

        assertEquals(descriptor, simpleType.getDescriptor());

        assertTrue("Descriptor does not use sequencing", descriptor.usesSequenceNumbers());
        verifySequencingConfig(dynamicHelper.getSession(), descriptor);
    }

    protected void verifySequencingConfig(Session session, ClassDescriptor descriptor) {
    }

    @Test
    public void createSingleInstances() throws Exception {
        DynamicEntity simpleInstance = createSimpleInstance(dynamicHelper, session, 1);

        ReportQuery countQuery = dynamicHelper.newReportQuery(ENTITY_TYPE, new ExpressionBuilder());
        countQuery.addCount();
        countQuery.setShouldReturnSingleValue(true);

        assertEquals(1, count(dynamicHelper, session));

        IdentityMapAccessor cache = session.getIdentityMapAccessor();
        assertTrue(cache.containsObjectInIdentityMap(simpleInstance));
        cache.initializeAllIdentityMaps();

        DynamicEntity findResult = find(dynamicHelper, session, 1);

        assertNotNull(findResult);
        assertEquals(simpleInstance.<Integer>get("id"), findResult.<Integer>get("id"));
        assertEquals(simpleInstance.<String>get("value1"), findResult.<String>get("value1"));

        session.release();
    }

    @Test
    public void createTwoInstances() throws DatabaseException, Exception {
        DynamicEntity simpleInstance1 = createSimpleInstance(dynamicHelper, session, 1);
        DynamicEntity simpleInstance2 = createSimpleInstance(dynamicHelper, session, 2);

        ReportQuery countQuery = dynamicHelper.newReportQuery(ENTITY_TYPE, new ExpressionBuilder());
        countQuery.addCount();
        countQuery.setShouldReturnSingleValue(true);

        assertEquals(2, count(dynamicHelper, session));

        IdentityMapAccessor cache = session.getIdentityMapAccessor();
        assertTrue(cache.containsObjectInIdentityMap(simpleInstance1));
        assertTrue(cache.containsObjectInIdentityMap(simpleInstance2));

        cache.initializeAllIdentityMaps();

        DynamicEntity findResult1 = find(dynamicHelper, session, 1);
        DynamicEntity findResult2 = find(dynamicHelper, session, 2);

        assertNotNull(findResult1);
        assertNotNull(findResult2);
        assertEquals(simpleInstance1.<Integer>get("id"), findResult1.<Integer>get("id"));
        assertEquals(simpleInstance2.<String>get("value1"), findResult2.<String>get("value1"));

        session.release();
    }

    protected DynamicEntity find(DynamicHelper helper, Session session, int id) {
        ReadObjectQuery findQuery = helper.newReadObjectQuery(ENTITY_TYPE);
        findQuery.setSelectionCriteria(findQuery.getExpressionBuilder().get("id").equal(id));
        return (DynamicEntity) session.executeQuery(findQuery);
    }

    protected int count(DynamicHelper helper, Session session) {
        ReportQuery countQuery = helper.newReportQuery(ENTITY_TYPE, new ExpressionBuilder());
        countQuery.addCount();
        countQuery.setShouldReturnSingleValue(true);

        return ((Number) session.executeQuery(countQuery)).intValue();
    }

    protected DynamicEntity createSimpleInstance(DynamicHelper helper, Session session, int expectedId) {
        DynamicType simpleEntityType = helper.getType(ENTITY_TYPE);
        assertNotNull(simpleEntityType);

        DynamicEntity simpleInstance = simpleEntityType.newDynamicEntity();
        simpleInstance.set("value1", TABLE_NAME);

        UnitOfWork uow = session.acquireUnitOfWork();

        assertEquals(0, ((Number) simpleInstance.get("id")).intValue());
        uow.registerNewObject(simpleInstance);
        assertEquals(0, ((Number) simpleInstance.get("id")).intValue());

        // uow.assignSequenceNumber(simpleInstance);

        uow.commit();
        assertEquals(expectedId, ((Number)simpleInstance.get("id")).intValue());

        return simpleInstance;
    }

}
