/*
 * Copyright 2009 Google Inc.
 *
 * 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 com.google.gwt.dev.shell;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.dev.shell.BrowserChannel.CheckVersionsMessage;
import com.google.gwt.dev.shell.BrowserChannel.LoadModuleMessage;
import com.google.gwt.dev.shell.BrowserChannel.MessageType;
import com.google.gwt.dev.shell.BrowserChannel.OldLoadModuleMessage;
import com.google.gwt.dev.shell.BrowserChannel.ProtocolVersionMessage;
import com.google.gwt.dev.shell.BrowserChannel.QuitMessage;
import com.google.gwt.dev.shell.BrowserChannel.RequestIconMessage;
import com.google.gwt.dev.shell.BrowserChannel.ReturnMessage;
import com.google.gwt.dev.shell.BrowserChannel.UserAgentIconMessage;
import com.google.gwt.dev.shell.BrowserChannel.Value;
import com.google.gwt.dev.shell.BrowserChannelServer.SessionHandlerServer;
import com.google.gwt.dev.util.log.dashboard.DashboardNotifier;

import junit.framework.TestCase;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.concurrent.Semaphore;

/**
 * Test that the protocol startup of BrowserChannelworks for all supported
 * protocol versions.
 */
public class BrowserChannelServerTest extends TestCase {

  /**
   * A BrowserChannelServer that can notify when the connection is closed. It
   * also uses a custom {@code DashboardNotifier} in order to test notification
   * calls.
   */
  private class TestBrowserChannelServer extends BrowserChannelServer {

    TestDashboardNotifier notifier = new TestDashboardNotifier();

    private final Semaphore finishNotify = new Semaphore(0);

    public TestBrowserChannelServer(TreeLogger logger,
        InputStream inputStream, OutputStream outputStream,
        SessionHandlerServer handler) {
      super(logger, inputStream, outputStream, handler, true);
    }

    @Override
    public void run() {
      super.run();
      finishNotify.release();
    }

    @Override
    DashboardNotifier getDashboardNotifier() {
      return notifier;
    }

    public void waitForClose() throws InterruptedException {
      finishNotify.acquire();
    }
  }

  /**
   * Maintains a connected pair of piped streams.
   */
  private class PipedStreamPair {

    private final PipedOutputStream output;
    private final PipedInputStream input;

    public PipedStreamPair() {
      PipedOutputStream out = null;
      PipedInputStream in = null;
      try {
        out = new PipedOutputStream();
        in = new PipedInputStream(out);
      } catch (IOException e) {
      }
      output = out;
      input = in;
    }

    public PipedInputStream getInputStream() {
      return input;
    }

    public PipedOutputStream getOutputStream() {
      return output;
    }
  }

  /**
   * A SessionHandler which keeps track of parameters from the LoadModule
   * message, but mocks out everything else.
   */
  private static class TestSessionHandler extends SessionHandlerServer {

    private String loadedModule;
    private String userAgent;
    private String url;
    private String tabKey;
    private String sessionKey;
    private byte[] userAgentIcon;
    private String moduleName;

    @Override
    public void freeValue(BrowserChannelServer channel, int[] ids) {
    }

    public String getLoadedModule() {
      return loadedModule;
    }

    public String getModuleName() {
      return moduleName;
    }

    @Override
    public ExceptionOrReturnValue getProperty(BrowserChannelServer channel,
        int refId, int dispId) {
      return new ExceptionOrReturnValue(false, new Value());
    }

    public String getSessionKey() {
      return sessionKey;
    }

    public String getTabKey() {
      return tabKey;
    }

    public String getUrl() {
      return url;
    }

    public String getUserAgent() {
      return userAgent;
    }

    public byte[] getUserAgentIcon() {
      return userAgentIcon;
    }

    @Override
    public ExceptionOrReturnValue invoke(BrowserChannelServer channel, Value thisObj,
        int dispId, Value[] args) {
      return new ExceptionOrReturnValue(false, new Value());
    }

    @Override
    public TreeLogger loadModule(BrowserChannelServer channel, String moduleName,
        String userAgent, String url, String tabKey, String sessionKey,
        byte[] userAgentIcon) {
      loadedModule = moduleName;
      this.moduleName = moduleName;
      this.userAgent = userAgent;
      this.url = url;
      this.tabKey = tabKey;
      this.sessionKey = sessionKey;
      this.userAgentIcon = userAgentIcon;
      return new FailErrorLogger();
    }

    @Override
    public ExceptionOrReturnValue setProperty(BrowserChannelServer channel,
        int refId, int dispId, Value newValue) {
      return new ExceptionOrReturnValue(false, new Value());
    }

    @Override
    public void unloadModule(BrowserChannelServer channel, String moduleName) {
      loadedModule = null;
    }
  }

  /**
   * A dashboard notifier that enforces the correct method calls.
   */
  private static class TestDashboardNotifier implements DashboardNotifier {
    DevModeSession currentSession;
    boolean started;
    boolean ended;

    @Override
    public void devModeEventBegin() {
      fail("BrowserChannelServer should not be calling DashboardNotifier.devModeEventBegin()");
    }

    @Override
    public void devModeEventEnd(DevModeSession session, String eventType, long startTimeNanos,
        long durationNanos) {
      fail("BrowserChannelServer should not be calling DashboardNotifier.devModeEventEnd()");
    }

    @Override
    public void devModeSessionBegin(DevModeSession session) {
      currentSession = session;
      assertFalse("DashboardNotifier.devModeSessionBegin() called more than once", started);
      started = true;
    }

    @Override
    public void devModeSessionEnd(DevModeSession session) {
      assertTrue("DashboardNotifier.devModeSessionEnd() without prior call to "
          + "DashboardNotifier.devModeSessionBegin()", started);
      assertFalse("DashboardNotifier.devModeSessionEnd() called more than once", ended);
      assertEquals("Wrong session passed to DashboardNotifier.devModeSessionEnd()",
          currentSession, session);
      ended = true;
    }

    public void verify(String moduleName, String userAgent) {
      assertTrue(started);
      assertTrue(ended);
      assertEquals(moduleName, currentSession.getModuleName());
      assertEquals(userAgent, currentSession.getUserAgent());
    }
  }

  private PipedStreamPair clientToServer = new PipedStreamPair();
  private PipedStreamPair serverToClient = new PipedStreamPair();

  /**
   * Test a version 1 client interacting with the server.
   *
   * @throws IOException
   * @throws BrowserChannelException
   * @throws InterruptedException
   */
  public void testVersion1() throws IOException, BrowserChannelException,
      InterruptedException {
    TestSessionHandler handler = new TestSessionHandler();
    TestBrowserChannelServer server = new TestBrowserChannelServer(
        new FailErrorLogger(), clientToServer.getInputStream(),
        serverToClient.getOutputStream(), handler);
    TestBrowserChannel client = new TestBrowserChannel(
        serverToClient.getInputStream(), clientToServer.getOutputStream());
    new OldLoadModuleMessage(client, 1, "testModule", "userAgent").send();
    MessageType type = client.readMessageType();
    assertEquals("testModule", handler.getModuleName());
    assertEquals("userAgent", handler.getUserAgent());
    assertNull(handler.getUrl());
    assertNull(handler.getTabKey());
    assertNull(handler.getSessionKey());
    assertNull(handler.getUserAgentIcon());
    assertEquals(MessageType.RETURN, type);
    DevModeSession session = server.getDevModeSession();
    assertNotNull(session);
    assertEquals("testModule", session.getModuleName());
    assertEquals("userAgent", session.getUserAgent());
    ReturnMessage.receive(client);
    QuitMessage.send(client);
    server.waitForClose();
    assertNull(handler.getLoadedModule());
    server.notifier.verify("testModule", "userAgent");
  }

  /**
   * Test a version 2 client interacting with the server.
   *
   * @throws IOException
   * @throws BrowserChannelException
   * @throws InterruptedException
   */
  public void testVersion2() throws IOException, BrowserChannelException,
      InterruptedException {
    TestSessionHandler handler = new TestSessionHandler();
    TestBrowserChannelServer server = new TestBrowserChannelServer(
        new FailErrorLogger(), clientToServer.getInputStream(),
        serverToClient.getOutputStream(), handler);
    TestBrowserChannel client = new TestBrowserChannel(
        serverToClient.getInputStream(), clientToServer.getOutputStream());
    new CheckVersionsMessage(client, 2, 2,
        HostedHtmlVersion.EXPECTED_GWT_ONLOAD_VERSION).send();
    MessageType type = client.readMessageType();
    assertEquals(MessageType.PROTOCOL_VERSION, type);
    ProtocolVersionMessage protocolMessage = ProtocolVersionMessage.receive(
        client);
    assertEquals(2, protocolMessage.getProtocolVersion());
    new LoadModuleMessage(client, "url", "tabkey", "session", "testModule",
        "userAgent").send();
    type = client.readMessageType();
    assertEquals("testModule", handler.getModuleName());
    assertEquals("userAgent", handler.getUserAgent());
    assertEquals("url", handler.getUrl());
    assertEquals("tabkey", handler.getTabKey());
    assertEquals("session", handler.getSessionKey());
    assertNull(handler.getUserAgentIcon());
    assertEquals(MessageType.RETURN, type);
    DevModeSession session = server.getDevModeSession();
    assertNotNull(session);
    assertEquals("testModule", session.getModuleName());
    assertEquals("userAgent", session.getUserAgent());
    ReturnMessage.receive(client);
    QuitMessage.send(client);
    server.waitForClose();
    assertNull(handler.getLoadedModule());
    server.notifier.verify("testModule", "userAgent");
  }

  /**
   * Test a version 3 client interacting with the server.
   *
   * @throws IOException
   * @throws BrowserChannelException
   * @throws InterruptedException
   */
  public void testVersion3() throws IOException, BrowserChannelException,
      InterruptedException {
    TestSessionHandler handler = new TestSessionHandler();
    TestBrowserChannelServer server = new TestBrowserChannelServer(
        new FailErrorLogger(), clientToServer.getInputStream(),
        serverToClient.getOutputStream(), handler);
    TestBrowserChannel client = new TestBrowserChannel(
        serverToClient.getInputStream(), clientToServer.getOutputStream());
    new CheckVersionsMessage(client, 2, 3,
        HostedHtmlVersion.EXPECTED_GWT_ONLOAD_VERSION).send();
    MessageType type = client.readMessageType();
    assertEquals(MessageType.PROTOCOL_VERSION, type);
    ProtocolVersionMessage protocolMessage = ProtocolVersionMessage.receive(
        client);
    assertEquals(3, protocolMessage.getProtocolVersion());
    new LoadModuleMessage(client, "url", "tabkey", "session", "testModule",
        "userAgent").send();
    type = client.readMessageType();
    byte[] iconBytes = null;
    if (type == MessageType.REQUEST_ICON) {
      RequestIconMessage.receive(client);
      iconBytes = new byte[] { 0, 1, 2, 3, 4, 5 };
      UserAgentIconMessage.send(client, iconBytes);
      type = client.readMessageType();
    }
    assertEquals("testModule", handler.getModuleName());
    assertEquals("userAgent", handler.getUserAgent());
    assertEquals("url", handler.getUrl());
    assertEquals("tabkey", handler.getTabKey());
    assertEquals("session", handler.getSessionKey());
    byte[] receivedIcon = handler.getUserAgentIcon();
    assertNotNull(receivedIcon);
    assertEquals(iconBytes.length, receivedIcon.length);
    for (int i = 0; i < iconBytes.length; ++i) {
      assertEquals(iconBytes[i], receivedIcon[i]);
    }
    assertEquals(MessageType.RETURN, type);
    DevModeSession session = server.getDevModeSession();
    assertNotNull(session);
    assertEquals("testModule", session.getModuleName());
    assertEquals("userAgent", session.getUserAgent());
    ReturnMessage.receive(client);
    QuitMessage.send(client);
    server.waitForClose();
    assertNull(handler.getLoadedModule());
    server.notifier.verify("testModule", "userAgent");
  }
}
