package cc.blynk.integration;

import cc.blynk.common.enums.Command;
import cc.blynk.integration.model.ClientPair;
import cc.blynk.server.Server;
import org.apache.commons.io.FileUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import static cc.blynk.common.enums.Response.OK;
import static cc.blynk.common.enums.Response.TWEET_EXCEPTION;
import static cc.blynk.common.model.messages.MessageFactory.produce;
import static org.mockito.Mockito.*;

/**
 * The Blynk Project.
 * Created by Dmitriy Dumanskiy.
 * Created on 2/2/2015.
 *
 */
@RunWith(MockitoJUnitRunner.class)
public class MainWorkflowTest extends IntegrationBase {

    private Server server;

    @Before
    public void init() throws Exception {
        initServerStructures();

        FileUtils.deleteDirectory(fileManager.getDataDir().toFile());

        server = new Server(properties, fileManager, sessionsHolder, userRegistry, stats);
        new Thread(server).start();

        //wait util server start.
        sleep(500);
    }

    @After
    public void shutdown() {
        server.stop();
    }

    @Test
    public void testConnectAppAndHardware() throws Exception {
        initAppAndHardPair("localhost", TEST_PORT);
    }

    @Test
    public void testTweetException() throws Exception {
        ClientPair clientPair = initAppAndHardPair("localhost", TEST_PORT);
        String userProfile = readTestUserProfile();
        clientPair.appClient.send("saveProfile " + userProfile);
        clientPair.hardwareClient.send("tweet 123");

        //waiting request to be send to twitter
        sleep(2000);

        verify(clientPair.hardwareClient.responseMock).channelRead(any(), eq(produce(1, TWEET_EXCEPTION)));
    }

    @Test
    public void testAppSendHardCommandAndBack() throws Exception {
        ClientPair clientPair = initAppAndHardPair("localhost", TEST_PORT);
        clientPair.appClient.send("hardware 1 1");
        verify(clientPair.hardwareClient.responseMock).channelRead(any(), eq(produce(1, Command.HARDWARE_COMMAND, "1 1".replaceAll(" ", "\0"))));

        clientPair.hardwareClient.send("hardware 1 1");
        verify(clientPair.appClient.responseMock).channelRead(any(), eq(produce(1, OK)));
        verify(clientPair.appClient.responseMock).channelRead(any(), eq(produce(1, Command.HARDWARE_COMMAND, "1 1".replaceAll(" ", "\0"))));
    }


    @Test
    public void testConnectAppAndHardwareAndSendCommands() throws Exception {
        ClientPair clientPair = initAppAndHardPair("localhost", TEST_PORT);



        long start = System.currentTimeMillis();
        for (int i = 0; i < 100; i++) {
            clientPair.appClient.sendNoSleep("hardware 1 1");
        }
        System.out.println("Time : " + (System.currentTimeMillis() - start));

        sleep(500);

        for (int i = 1; i <= 100; i++) {
            verify(clientPair.appClient.responseMock).channelRead(any(), eq(produce(i, OK)));
        }
        verify(clientPair.hardwareClient.responseMock, times(100)).channelRead(any(), any());
    }

}

@@ -62,16 +62,63 @@
 ommand;%0A
+import cc.blynk.common.model.messages.Message;%0A
 import c
@@ -155,16 +155,16 @@
 ntPair;%0A
-
 import c
@@ -331,16 +331,51 @@
 unWith;%0A
+import org.mockito.ArgumentCaptor;%0A
 import o
@@ -414,16 +414,40 @@
 unner;%0A%0A
+import java.util.List;%0A%0A
 import s
@@ -549,16 +549,16 @@
 EPTION;%0A
-
 import s
@@ -618,16 +618,104 @@
 roduce;%0A
+import static org.junit.Assert.assertEquals;%0Aimport static org.junit.Assert.assertTrue;%0A
 import s
@@ -2399,32 +2399,128 @@
 %22hardware 1 1%22);
+%0A%0A        ArgumentCaptor%3CMessage%3E objectArgumentCaptor = ArgumentCaptor.forClass(Message.class);
 %0A        verify(
@@ -2544,32 +2544,42 @@
 ent.responseMock
+, times(2)
 ).channelRead(an
@@ -2587,37 +2587,50 @@
 (), 
-eq(produce(1, OK)
+objectArgumentCaptor.capture(
 ));%0A
+%0A
         
 veri
@@ -2629,113 +2629,383 @@
     
-verify(clientPair.appClient.responseMock).channelRead(any(), eq(produce(1, Command.HARDWARE_COMMAND, 
+List%3CMessage%3E arguments = objectArgumentCaptor.getAllValues();%0A        assertEquals(produce(1, OK), arguments.get(0));%0A        Message hardMessage = arguments.get(1);%0A        assertEquals(1, hardMessage.id);%0A        assertEquals(Command.HARDWARE_COMMAND, hardMessage.command);%0A        assertEquals(17, hardMessage.length);%0A        assertTrue(hardMessage.body.startsWith(
 %221 1
+ 
 %22.re
@@ -3025,26 +3025,129 @@
  %22%5C0%22)))
-)
 ;
+%0A%0A       // return msg.id == 1 && msg.command == Command.HARDWARE_COMMAND && msg.body.startsWith(%221%22);%0A%0A
 %0A    %7D%0A%0A
 %0A    @Te
@@ -3138,17 +3138,16 @@
 %0A    %7D%0A%0A
-%0A
     @Tes

Test fix after code changes.