/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.apache.zeppelin.r;

import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import org.apache.commons.io.IOUtils;
import org.apache.zeppelin.interpreter.InterpreterContext;
import org.apache.zeppelin.interpreter.InterpreterException;
import org.apache.zeppelin.interpreter.InterpreterGroup;
import org.apache.zeppelin.interpreter.InterpreterOutput;
import org.apache.zeppelin.interpreter.InterpreterResult;
import org.apache.zeppelin.interpreter.InterpreterResultMessage;
import org.apache.zeppelin.interpreter.LazyOpenInterpreter;
import org.apache.zeppelin.interpreter.remote.RemoteInterpreterEventClient;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;

public class ShinyInterpreterTest {

  protected ShinyInterpreter interpreter;

  @Before
  public void setUp() throws InterpreterException {
    Properties properties = new Properties();

    InterpreterContext context = getInterpreterContext();
    InterpreterContext.set(context);
    interpreter = new ShinyInterpreter(properties);

    InterpreterGroup interpreterGroup = new InterpreterGroup();
    interpreterGroup.addInterpreterToSession(new LazyOpenInterpreter(interpreter), "session_1");
    interpreter.setInterpreterGroup(interpreterGroup);

    interpreter.open();
  }

  @After
  public void tearDown() throws InterpreterException {
    if (interpreter != null) {
      interpreter.close();
    }
  }

  @Test
  public void testShinyApp() throws
          IOException, InterpreterException, InterruptedException, UnirestException {
    /****************** Launch Shiny app with default app name *****************************/
    InterpreterContext context = getInterpreterContext();
    context.getLocalProperties().put("type", "ui");
    InterpreterResult result =
            interpreter.interpret(IOUtils.toString(getClass().getResource("/ui.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    context = getInterpreterContext();
    context.getLocalProperties().put("type", "server");
    result = interpreter.interpret(IOUtils.toString(getClass().getResource("/server.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    final InterpreterContext context2 = getInterpreterContext();
    context2.getLocalProperties().put("type", "run");
    Thread thread = new Thread(() -> {
      try {
        interpreter.interpret("", context2);
      } catch (Exception e) {
        e.printStackTrace();
      }
    });
    thread.start();
    // wait for the shiny app start
    Thread.sleep(5 * 1000);
    // extract shiny url
    List<InterpreterResultMessage> resultMessages = context2.out.toInterpreterResultMessage();
    assertEquals(1, resultMessages.size());
    assertEquals(InterpreterResult.Type.HTML, resultMessages.get(0).getType());
    String resultMessageData = resultMessages.get(0).getData();
    assertTrue(resultMessageData, resultMessageData.contains("<iframe"));
    Pattern urlPattern = Pattern.compile(".*src=\"(http\\S*)\".*", Pattern.DOTALL);
    Matcher matcher = urlPattern.matcher(resultMessageData);
    if (!matcher.matches()) {
      fail("Unable to extract url: " + resultMessageData);
    }
    String shinyURL = matcher.group(1);

    // verify shiny app via calling its rest api
    HttpResponse<String> response = Unirest.get(shinyURL).asString();
    assertEquals(200, response.getStatus());
    assertTrue(response.getBody(), response.getBody().contains("Shiny Text"));

    /************************ Launch another shiny app (app2) *****************************/
    context = getInterpreterContext();
    context.getLocalProperties().put("type", "ui");
    context.getLocalProperties().put("app", "app2");
    result =
            interpreter.interpret(IOUtils.toString(getClass().getResource("/ui.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    context = getInterpreterContext();
    context.getLocalProperties().put("type", "server");
    context.getLocalProperties().put("app", "app2");
    result = interpreter.interpret(IOUtils.toString(getClass().getResource("/server.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    final InterpreterContext context3 = getInterpreterContext();
    context3.getLocalProperties().put("type", "run");
    context3.getLocalProperties().put("app", "app2");
    thread = new Thread(() -> {
      try {
        interpreter.interpret("", context3);
      } catch (Exception e) {
        e.printStackTrace();
      }
    });
    thread.start();
    // wait for the shiny app start
    Thread.sleep(5 * 1000);
    // extract shiny url
    resultMessages = context3.out.toInterpreterResultMessage();
    assertEquals(1, resultMessages.size());
    assertEquals(InterpreterResult.Type.HTML, resultMessages.get(0).getType());
    resultMessageData = resultMessages.get(0).getData();
    assertTrue(resultMessageData, resultMessageData.contains("<iframe"));
    matcher = urlPattern.matcher(resultMessageData);
    if (!matcher.matches()) {
      fail("Unable to extract url: " + resultMessageData);
    }
    String shinyURL2 = matcher.group(1);

    // verify shiny app via calling its rest api
    response = Unirest.get(shinyURL2).asString();
    assertEquals(200, response.getStatus());
    assertTrue(response.getBody(), response.getBody().contains("Shiny Text"));

    // cancel paragraph to stop the first shiny app
    interpreter.cancel(getInterpreterContext());
    // wait for shiny app to be stopped
    Thread.sleep(1000);
    try {
      Unirest.get(shinyURL).asString();
      fail("Should fail to connect to shiny app");
    } catch (Exception e) {
      assertTrue(e.getMessage(), e.getMessage().contains("Connection refused"));
    }

    // the second shiny app still works
    response = Unirest.get(shinyURL2).asString();
    assertEquals(200, response.getStatus());
    assertTrue(response.getBody(), response.getBody().contains("Shiny Text"));
  }

  @Test
  public void testInvalidShinyApp()
          throws IOException, InterpreterException, InterruptedException, UnirestException {
    InterpreterContext context = getInterpreterContext();
    context.getLocalProperties().put("type", "ui");
    InterpreterResult result =
            interpreter.interpret(IOUtils.toString(getClass().getResource("/invalid_ui.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    context = getInterpreterContext();
    context.getLocalProperties().put("type", "server");
    result = interpreter.interpret(IOUtils.toString(getClass().getResource("/server.R")), context);
    assertEquals(InterpreterResult.Code.SUCCESS, result.code());

    final InterpreterContext context2 = getInterpreterContext();
    context2.getLocalProperties().put("type", "run");
    Thread thread = new Thread(() -> {
      try {
        interpreter.interpret("", context2);
      } catch (Exception e) {
        e.printStackTrace();
      }
    });
    thread.start();
    // wait for the shiny app start
    Thread.sleep(5 * 1000);
    List<InterpreterResultMessage> resultMessages = context2.out.toInterpreterResultMessage();
    assertEquals(1, resultMessages.size());
    assertEquals(InterpreterResult.Type.HTML, resultMessages.get(0).getType());
    String resultMessageData = resultMessages.get(0).getData();
    assertTrue(resultMessageData, resultMessageData.contains("<iframe"));
    Pattern urlPattern = Pattern.compile(".*src=\"(http\\S*)\".*", Pattern.DOTALL);
    Matcher matcher = urlPattern.matcher(resultMessageData);
    if (!matcher.matches()) {
      fail("Unable to extract url: " + resultMessageData);
    }
    String shinyURL = matcher.group(1);

    // call shiny app via rest api
    HttpResponse<String> response = Unirest.get(shinyURL).asString();
    assertEquals(500, response.getStatus());

    resultMessages = context2.out.toInterpreterResultMessage();
    assertTrue(resultMessages.get(1).getData(),
            resultMessages.get(1).getData().contains("object 'Invalid_code' not found"));

    // cancel paragraph to stop shiny app
    interpreter.cancel(getInterpreterContext());
    // wait for shiny app to be stopped
    Thread.sleep(1000);
    try {
      Unirest.get(shinyURL).asString();
      fail("Should fail to connect to shiny app");
    } catch (Exception e) {
      assertTrue(e.getMessage(), e.getMessage().contains("Connection refused"));
    }
  }

  protected InterpreterContext getInterpreterContext() {
    InterpreterContext context = InterpreterContext.builder()
            .setNoteId("note_1")
            .setParagraphId("paragraph_1")
            .setInterpreterOut(new InterpreterOutput(null))
            .setLocalProperties(new HashMap<>())
            .setInterpreterClassName(ShinyInterpreter.class.getName())
            .setIntpEventClient(mock(RemoteInterpreterEventClient.class))
            .build();
    return context;
  }
}
