package com.tibbo.aggregate.common.expression.util.update;

import static org.junit.Assert.assertEquals;

import com.tibbo.aggregate.common.expression.Expression;
import com.tibbo.aggregate.common.util.SyntaxErrorException;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;

/**
 * @author Vladimir Plizga
 * @since 06.12.2022
 */
public class ReferencesContextUpdaterTest
{

    @Test
    public void multipleReferencesUpdated() throws SyntaxErrorException
    {
        // given
        String oldContext = "users.admin.devices.runner";
        String newContext = "users.admin.devices.runner-clone";
        ReferencesContextUpdater sut = new ReferencesContextUpdater(oldContext, newContext);
        String sourceExpressionText =
                "  {users.admin.devices.runner:table$int[0]} + '_' \n" +
                "+ {users.admin.devices.runner_copy:table$int[1]} + '_' \n" +
                "+ {users.admin.devices.runner:table$int[2]}\n";
        Expression sourceExpression = new Expression(sourceExpressionText);

        // when
        Expression updatedExpression = sut.updateContextInExpressionReferences(sourceExpression);

        // then
        Expression expectedExpression = new Expression(
                "  {users.admin.devices.runner-clone:table$int[0]} + '_'  " +
                "+ {users.admin.devices.runner_copy:table$int[1]} + '_'  " +
                "+ {users.admin.devices.runner-clone:table$int[2]}");
        assertEquals(expectedExpression,  updatedExpression);
    }

    @Test
    public void noReferencesUpdated() throws SyntaxErrorException
    {
        // given
        String oldContext = "users.admin.devices.runner";
        String newContext = "users.admin.devices.runner-clone";
        ReferencesContextUpdater sut = new ReferencesContextUpdater(oldContext, newContext);
        String sourceExpressionText =
                "  {users.admin.devices.runner_copy:table$int[0]} + '_' \n" +
                "+ {users.admin.devices.runner_copy:table$int[1]} + '_' \n" +
                "+ {users.admin.devices.runner_copy:table$int[2]}\n";
        Expression sourceExpression = new Expression(sourceExpressionText);

        // when
        Expression updatedExpression = sut.updateContextInExpressionReferences(sourceExpression);

        // then
        assertEquals(sourceExpression,  updatedExpression);
    }

    @Test
    public void multilineReferenceUpdated() throws SyntaxErrorException
    {
        String sourceWinBasedExpressionText = prepareExpressionWithLineSeparator("\r\n");
        String sourceUnixBasedExpressionText = prepareExpressionWithLineSeparator("\n");
        assertExpressionUpdate(sourceWinBasedExpressionText);
        assertExpressionUpdate(sourceUnixBasedExpressionText);
    }

    private void assertExpressionUpdate(String sourceWinBasedExpressionText) throws SyntaxErrorException {
        // given
        String oldContext = "users.admin.devices.runner";
        String newContext = "users.admin.devices.runner-clone";
        ReferencesContextUpdater sut = new ReferencesContextUpdater(oldContext, newContext);

        Expression sourceExpression = new Expression(sourceWinBasedExpressionText);
        // when
        Expression updatedExpression = sut.updateContextInExpressionReferences(sourceExpression);
        // then
        Expression expectedExpression = new Expression("addRecords(   " +
                "clear({form/users.admin.devices.runner-clone:variableData})   " +
                ", \"value\"   , \"users.admin.devices.virtual\"   , \"NONE\"   , \"sine\"    , \"{value}\" )");
        // then
        Assertions.assertEquals(expectedExpression,  updatedExpression);
    }

    private String prepareExpressionWithLineSeparator(String separator) {
        return "addRecords(" + separator +
                "  clear({form/users.admin.devices.runner:variableData})" + separator +
                "  , \"value\"" + separator +
                "  , \"users.admin.devices.virtual\"" + separator +
                "  , \"NONE\"" + separator +
                "  , \"sine\" " + separator +
                "  , \"{value}\"" + separator +
                ")";
    }

    @Test(expected = IllegalArgumentException.class)
    public void equalContextsAreProhibited()
    {
        // given
        String oldContext = "users.admin.devices.runner";
        String newContext = "users.admin.devices.runner";

        // when
        new ReferencesContextUpdater(oldContext, newContext);

        // then
    }
}