/*
 * Copyright 2017, 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 io.spine.tools.protoc;

import com.google.protobuf.Message;
import io.spine.tools.protoc.test.ProtocPluginIntergrUserEvent;
import io.spine.tools.protoc.test.UserInfo;
import org.junit.Test;

import java.lang.reflect.Method;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

/**
 * @author Dmytro Dashenkov
 */
public class PluginShould {

    private static final String EVENT_INTERFACE_FQN = "io.spine.tools.protoc.ProtocPluginIntergrCustomerEvent";
    private static final String COMMAND_INTERFACE_FQN = "io.spine.tools.protoc.ProtocPluginIntergrCustomerCommand";
    private static final String USER_COMMAND_FQN = "io.spine.tools.protoc.ProtocPluginIntergrUserCommand";

    @Test
    public void generate_marker_interfaces() throws ClassNotFoundException {
        checkMarkerInterface(EVENT_INTERFACE_FQN);
    }

    @SuppressWarnings({"ConstantConditions", "RedundantCast"}) // Required by the test logic.
    @Test
    public void implement_marker_interfaces_in_generated_messages() {
        assertTrue((Object) ProtocPluginIntergrCustomerNotified.getDefaultInstance() instanceof ProtocPluginIntergrCustomerEvent);
        assertTrue((Object) ProtocPluginIntergrCustomerEmailRecieved.getDefaultInstance() instanceof ProtocPluginIntergrCustomerEvent);
    }

    @Test
    public void generate_marker_interfaces_for_separate_messages() throws ClassNotFoundException {
        checkMarkerInterface(COMMAND_INTERFACE_FQN);
    }

    @SuppressWarnings({"ConstantConditions", "RedundantCast"}) // Required by the test logic.
    @Test
    public void implement_interface_in_generated_messages_with_IS_option() {
        assertTrue((Object) ProtocPluginIntergrCustomerCreated.getDefaultInstance() instanceof ProtocPluginIntergrCustomerEvent);
        assertTrue((Object) ProtocPluginIntergrCreateCustomer.getDefaultInstance() instanceof ProtocPluginIntergrCustomerCommand);
    }

    @SuppressWarnings({"ConstantConditions", "RedundantCast"}) // Required by the test logic.
    @Test
    public void use_IS_in_priority_to_EVERY_IS() {
        assertTrue((Object) ProtocPluginIntergrUserCreated.getDefaultInstance() instanceof ProtocPluginIntergrUserEvent);
        assertTrue((Object) ProtocPluginIntergrUserNameUpdated.getDefaultInstance() instanceof ProtocPluginIntergrUserEvent);

        assertFalse((Object) UserName.getDefaultInstance() instanceof ProtocPluginIntergrUserEvent);
        assertTrue((Object) UserName.getDefaultInstance() instanceof UserInfo);
    }

    @Test
    public void resolve_packages_from_src_proto_if_not_specified() throws ClassNotFoundException {
        final Class<?> cls = checkMarkerInterface(USER_COMMAND_FQN);
        assertTrue(cls.isAssignableFrom(ProtocPluginIntergrCreateUser.class));
    }

    @Test
    public void skip_non_specified_message_types() {
        final Class<?> cls = CustomerName.class;
        final Class[] interfaces = cls.getInterfaces();
        assertEquals(1, interfaces.length);
        assertSame(CustomerNameOrBuilder.class, interfaces[0]);
    }

    private static Class<?> checkMarkerInterface(String fqn) throws ClassNotFoundException {
        final Class<?> cls = Class.forName(fqn);
        assertTrue(cls.isInterface());
        assertTrue(Message.class.isAssignableFrom(cls));

        final Method[] declaredMethods = cls.getDeclaredMethods();
        assertEquals(0, declaredMethods.length);
        return cls;
    }
}

@@ -1530,32 +1530,44 @@
 _INTERFACE_FQN =
+%0A           
  %22io.spine.tools
@@ -1660,24 +1660,36 @@
 ERFACE_FQN =
+%0A           
  %22io.spine.t
@@ -1787,16 +1787,28 @@
 ND_FQN =
+%0A           
  %22io.spi
@@ -2252,32 +2252,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot
@@ -2415,32 +2415,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot
@@ -2929,32 +2929,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot
@@ -3085,32 +3085,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot
@@ -3402,32 +3402,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot
@@ -3555,32 +3555,59 @@
 efaultInstance()
+%0A                          
  instanceof Prot

Fix code wrapping.