/*
 * 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 devModeEvent(DevModeSession session, String eventType, long startTimeNanos,
        long durationNanos) {
      fail("BrowserChannelServer should not be calling DashboardNotifier.devModeEvent()");
    }

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

    @Override
    public void devModeSessionEnded(DevModeSession session) {
      assertTrue("DashboardNotifier.devModeSessionEnded() without prior call to "
          + "DashboardNotifier.devModeSession()", started);
      assertFalse("DashboardNotifier.devModeSessionEnded() called more than once", ended);
      assertEquals("Wrong session passed to DashboardNotifier.devModeSessionEnded()",
          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");
  }
}
