/*
 * Copyright 2015, TeamDev Ltd. All rights reserved.
 *
 * Redistribution and use in source and/or binary forms, with or without
 * modification, must retain the above copyright notice and the following
 * disclaimer.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.spine3.server.projection;

import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.StringValue;
import com.google.protobuf.UInt32Value;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.spine3.base.EventContext;
import org.spine3.eventbus.Subscribe;

import javax.annotation.Nonnull;

import static org.junit.Assert.assertTrue;

@SuppressWarnings("InstanceMethodNamingConvention")
public class ProjectionShould {

    @SuppressWarnings("TypeMayBeWeakened") // We seek for Message types in event handlers, not MessageOfBuilders.
    private static class TestProjection extends Projection<Integer, StringValue> {

        protected TestProjection(Integer id) {
            super(id);
        }

        @Nonnull
        @Override
        protected StringValue getDefaultState() {
            return StringValue.getDefaultInstance();
        }

        @Subscribe
        public void on(StringValue event, EventContext ignored) {
            final StringValue newSate = createNewState("string", event.getValue());
            incrementState(newSate);
        }

        @Subscribe
        public void on(UInt32Value event, EventContext ignored) {
            final StringValue newSate = createNewState("integer", String.valueOf(event.getValue()));
            incrementState(newSate);
        }

        private StringValue createNewState(String type, String value) {
            final String currentState = getState().getValue();
            final String result = currentState + (currentState.length() > 0 ? " + " : "") +
                    type + '(' + value + ')' + System.lineSeparator();
            return StringValue.newBuilder().setValue(result).build();
        }

        /**
         * We expose this method to be called directly in {@link #setUp()}.
         * Normally this method would be called by a repository upon creation of a new instance.
         * This is checked by {@link #check_default_state_when_queried()}.
         */
        @Override
        @VisibleForTesting
        protected void setDefault() {
            super.setDefault();
        }
    }

    private TestProjection test;

    @Before
    public void setUp() {
        test = new TestProjection(1);
        test.setDefault();
    }

    /**
     * TODO:2015-11-02:alexander.litus: Entity returns default state instead of null now (like protobuf generated classes do).
     * If projection throws the exception in this case, it is the violation of Liskov Substitution principle.
     * So, should we remove this test?
     */
    @Ignore
    @Test(expected = IllegalStateException.class)
    public void check_default_state_when_queried() {
        final TestProjection test = new TestProjection(1);
        test.getState();
    }

    @Test
    public void handle_events() {
        final String stringValue = "something new";
        test.handle(StringValue.newBuilder().setValue(stringValue).build(), EventContext.getDefaultInstance());
        assertTrue(test.getState().getValue().contains(stringValue));

        final Integer integerValue = 1024;
        test.handle(UInt32Value.newBuilder().setValue(integerValue).build(), EventContext.getDefaultInstance());
        assertTrue(test.getState().getValue().contains(String.valueOf(integerValue)));
    }
}

@@ -1214,33 +1214,8 @@
 re;%0A
-import org.junit.Ignore;%0A
 impo
@@ -2919,83 +2919,8 @@
 ce.%0A
-         * This is checked by %7B@link #check_default_state_when_queried()%7D.%0A
     
@@ -3207,506 +3207,8 @@
  %7D%0A%0A
-    /**%0A     * TODO:2015-11-02:alexander.litus: Entity returns default state instead of null now (like protobuf generated classes do).%0A     * If projection throws the exception in this case, it is the violation of Liskov Substitution principle.%0A     * So, should we remove this test?%0A     */%0A    @Ignore%0A    @Test(expected = IllegalStateException.class)%0A    public void check_default_state_when_queried() %7B%0A        final TestProjection test = new TestProjection(1);%0A        test.getState();%0A    %7D%0A%0A
     

Remove deprecated test.