/*
 * Copyright 2016 MovingBlocks
 *
 * 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 org.terasology.config.flexible;

import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.runners.Enclosed;
import org.junit.runner.RunWith;
import org.terasology.config.flexible.validators.RangedNumberValidator;
import org.terasology.engine.SimpleUri;
import org.terasology.utilities.random.FastRandom;
import org.terasology.utilities.random.Random;

import java.beans.PropertyChangeListener;

import static org.junit.Assert.*;

@RunWith(Enclosed.class)
public class SettingTest {
    public static class SetValue {
        private Setting<Integer> setting;

        private int eventResult;

        @Before
        public void setUp() {
            setting = new SettingImpl<>(new SimpleUri("engine-tests:TestSetting"),
                    50, new RangedNumberValidator<>(0, 100, false, false));

            eventResult = -1;

            setting.subscribe(propertyChangeEvent -> eventResult = (int) propertyChangeEvent.getNewValue());
        }

        @Test
        public void testSetsValue() {
            assertTrue(setting.setValue(25));

            assertEquals(25, eventResult);
        }

        @Test
        public void testDoesNotSetValue() {
            assertFalse(setting.setValue(101));

            assertEquals(-1, eventResult);
        }
    }

    public static class Subscribers {
        private Setting<Integer> setting;

        private PropertyChangeListener listener;

        private int eventCallCount;

        @Before
        public void setUp() {
            setting = new SettingImpl<>(new SimpleUri("engine-tests:TestSetting"),
                    50, new RangedNumberValidator<>(0, 100, false, false));

            eventCallCount = 0;

            listener = propertyChangeEvent -> eventCallCount++;
        }

        @Test
        public void testHasSubscribers() {
            setting.subscribe(listener);

            assertTrue(setting.hasSubscribers());

            setting.unsubscribe(listener);

            assertFalse(setting.hasSubscribers());
        }

        @Test
        public void testSetEventCall() {
            setting.subscribe(listener);

            Random random = new FastRandom();

            final int n = 50;
            int expectedEventCallCount = 0;

            for (int i = 0; i < n; i++) {
                int r = random.nextInt(-50, 150);
                expectedEventCallCount += setting.setValue(r) ? 1 : 0;
            }

            assertEquals(expectedEventCallCount, eventCallCount);
        }

        @Test
        public void testSubscribe() {
            final int n = 10;

            for (int i = 0; i < n; i++) {
                setting.subscribe(propertyChangeEvent -> eventCallCount++);
            }

            setting.setValue(30);

            assertEquals(n, eventCallCount);
        }

        @Test
        public void testUnsubscribe() {
            int n = 10;

            PropertyChangeListener[] listeners = new PropertyChangeListener[n];

            for (int i = 0; i < n; i++) {
                listeners[i] = propertyChangeEvent -> eventCallCount++;
                setting.subscribe(listeners[i]);
            }

            int halfN = n / 2;

            for (int i = 0; i < new FastRandom().nextInt(halfN); i++) {
                setting.unsubscribe(listeners[i]);
                n--;
            }

            setting.setValue(30);

            assertEquals(n, eventCallCount);
        }
    }
}

@@ -1101,16 +1101,108 @@
 gTest %7B%0A
+    private static final SimpleUri SETTING_ID = new SimpleUri(%22engine-tests:TestSetting%22);%0A%0A
     publ
@@ -1395,49 +1395,18 @@
 l%3C%3E(
-new SimpleUri(%22engine-tests:TestSetting%22)
+SETTING_ID
 ,%0A  
@@ -2209,49 +2209,18 @@
 l%3C%3E(
-new SimpleUri(%22engine-tests:TestSetting%22)
+SETTING_ID
 ,%0A  
@@ -2824,17 +2824,35 @@
 nal int 
-n
+MAX_SET_VALUE_COUNT
  = 50;%0A 
@@ -2919,33 +2919,51 @@
 (int i = 0; i %3C 
-n
+MAX_SET_VALUE_COUNT
 ; i++) %7B%0A       
@@ -2976,16 +2976,24 @@
    int r
+andomInt
  = rando
@@ -3073,16 +3073,24 @@
 tValue(r
+andomInt
 ) ? 1 : 
@@ -3254,25 +3254,40 @@
   final int 
-n
+SUBSCRIBER_COUNT
  = 10;%0A%0A    
@@ -3306,33 +3306,48 @@
 (int i = 0; i %3C 
-n
+SUBSCRIBER_COUNT
 ; i++) %7B%0A       
@@ -3482,33 +3482,48 @@
    assertEquals(
-n
+SUBSCRIBER_COUNT
 , eventCallCount
@@ -3606,17 +3606,31 @@
     int 
-n
+subscriberCount
  = 10;%0A%0A
@@ -3705,17 +3705,31 @@
 istener%5B
-n
+subscriberCount
 %5D;%0A%0A    
@@ -3756,17 +3756,31 @@
  0; i %3C 
-n
+subscriberCount
 ; i++) %7B
@@ -3920,40 +3920,8 @@
  %7D%0A%0A
-            int halfN = n / 2;%0A%0A
     
@@ -3977,13 +3977,27 @@
 Int(
-halfN
+subscriberCount / 2
 ); i
@@ -4069,17 +4069,31 @@
         
-n
+subscriberCount
 --;%0A    
@@ -4163,17 +4163,31 @@
 tEquals(
-n
+subscriberCount
 , eventC

Refactor Setting tests to improve readability