package com.fwdekker.randomness.decimal;

import com.intellij.openapi.ui.ValidationInfo;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
import org.junit.Test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.swing.fixture.Containers.showInFrame;


/**
 * GUI tests for {@link DecimalSettingsDialog}.
 */
public final class DecimalSettingsDialogTest extends AssertJSwingJUnitTestCase {
    private static final double DEFAULT_MIN_VALUE = 157.61;
    private static final double DEFAULT_MAX_VALUE = 408.68;
    private static final int DEFAULT_DECIMAL_COUNT = 5;

    private DecimalSettings decimalSettings;
    private DecimalSettingsDialog decimalSettingsDialog;
    private FrameFixture frame;


    @Override
    protected void onSetUp() {
        decimalSettings = new DecimalSettings();
        decimalSettings.setMinValue(DEFAULT_MIN_VALUE);
        decimalSettings.setMaxValue(DEFAULT_MAX_VALUE);
        decimalSettings.setDecimalCount(DEFAULT_DECIMAL_COUNT);

        decimalSettingsDialog = GuiActionRunner.execute(() -> new DecimalSettingsDialog(decimalSettings));
        frame = showInFrame(robot(), decimalSettingsDialog.getContentPane());
    }


    @Test
    public void testDefaultMinValue() {
        frame.spinner("minValue").requireValue(DEFAULT_MIN_VALUE);
    }

    @Test
    public void testDefaultMaxValue() {
        frame.spinner("maxValue").requireValue(DEFAULT_MAX_VALUE);
    }

    @Test
    public void testDefaultDecimalCount() {
        frame.spinner("decimalCount").requireValue(DEFAULT_DECIMAL_COUNT);
    }

    @Test
    public void testDefaultIsValid() {
        assertThat(decimalSettingsDialog.doValidate()).isNull();
    }

    @Test
    public void testMinValueType() {
        GuiActionRunner.execute(() -> frame.spinner("minValue").target().setValue(396.28f));

        final ValidationInfo validationInfo = decimalSettingsDialog.doValidate();

        assertThat(validationInfo).isNotNull();
        assertThat(validationInfo.component).isEqualTo(frame.spinner("minValue").target());
        assertThat(validationInfo.message).isEqualTo("Minimum value must be a decimal.");
    }

    @Test
    public void testMaxValueType() {
        GuiActionRunner.execute(() -> frame.spinner("maxValue").target().setValue(355.28f));

        final ValidationInfo validationInfo = decimalSettingsDialog.doValidate();

        assertThat(validationInfo).isNotNull();
        assertThat(validationInfo.component).isEqualTo(frame.spinner("maxValue").target());
        assertThat(validationInfo.message).isEqualTo("Maximum value must be a decimal.");
    }

    @Test
    public void testDecimalCountType() {
        GuiActionRunner.execute(() -> frame.spinner("decimalCount").target().setValue(166.98));

        final ValidationInfo validationInfo = decimalSettingsDialog.doValidate();

        assertThat(validationInfo).isNotNull();
        assertThat(validationInfo.component).isEqualTo(frame.spinner("decimalCount").target());
        assertThat(validationInfo.message).isEqualTo("Decimal count must be an integer.");
    }

    @Test
    public void testMaxValueGreaterThanMinValue() {
        frame.spinner("maxValue").enterTextAndCommit(Integer.toString((int) DEFAULT_MIN_VALUE - 1));

        final ValidationInfo validationInfo = decimalSettingsDialog.doValidate();

        assertThat(validationInfo).isNotNull();
        assertThat(validationInfo.component).isEqualTo(frame.spinner("maxValue").target());
        assertThat(validationInfo.message).isEqualTo("Maximum value cannot be smaller than minimum value.");
    }

    @Test
    public void testNegativeDecimalCount() {
        frame.spinner("decimalCount").enterTextAndCommit(Double.toString(-851));

        final ValidationInfo validationInfo = decimalSettingsDialog.doValidate();

        assertThat(validationInfo).isNotNull();
        assertThat(validationInfo.component).isEqualTo(frame.spinner("decimalCount").target());
        assertThat(validationInfo.message).isEqualTo("Decimal count must be at least 0.");
    }

    @Test
    public void testSaveSettings() {
        frame.spinner("minValue").enterText("418.63");
        frame.spinner("maxValue").enterText("858.59");
        frame.spinner("decimalCount").enterText("99");

        GuiActionRunner.execute(() -> decimalSettingsDialog.saveSettings());

        assertThat(decimalSettings.getMinValue()).isEqualTo(418.63);
        assertThat(decimalSettings.getMaxValue()).isEqualTo(858.59);
        assertThat(decimalSettings.getDecimalCount()).isEqualTo(99);
    }
}

@@ -82,16 +82,72 @@
 onInfo;%0A
+import java.text.NumberFormat;%0Aimport java.util.Locale;%0A
 import o
@@ -3879,14 +3879,15 @@
 mit(
-Double
+Integer
 .toS
@@ -4321,16 +4321,30 @@
 ext(
-%22
+doubleToString(
 418.63
-%22
+)
 );%0A 
@@ -4390,16 +4390,30 @@
 ext(
-%22
+doubleToString(
 858.59
-%22
+)
 );%0A 
@@ -4679,24 +4679,24 @@
 To(858.59);%0A
-
         asse
@@ -4758,10 +4758,455 @@
 ;%0A    %7D%0A
+%0A%0A    /**%0A     * Locale-dependently converts a double into a string.%0A     *%0A     * @param decimal a double%0A     * @return the user's locale's representation of the given double%0A     */%0A    private static String doubleToString(final double decimal) %7B%0A        final Locale locale = Locale.getDefault(Locale.Category.FORMAT);%0A        final NumberFormat formatter = NumberFormat.getInstance(locale);%0A%0A        return formatter.format(decimal);%0A    %7D%0A
 %7D%0A

Fix locale dependency in tests