/*
 * Copyright 2008 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.
 */

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cerrno>

#include "Debug.h"

#ifdef _WINDOWS
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <sys/time.h>
#endif
#include <time.h>

#include "Platform.h"
#include "ByteOrder.h"

#include "CheckVersionsMessage.h"
#include "ProtocolVersionMessage.h"
#include "ChooseTransportMessage.h"
#include "SwitchTransportMessage.h"
#include "FatalErrorMessage.h"
#include "FreeValueMessage.h"
#include "HostChannel.h"
#include "LoadJsniMessage.h"
#include "InvokeMessage.h"
#include "InvokeSpecialMessage.h"
#include "QuitMessage.h"
#include "ReturnMessage.h"
#include "Value.h"
#include "scoped_ptr/scoped_ptr.h"

using namespace std;

ByteOrder HostChannel::byteOrder;

bool HostChannel::connectToHost(const char* host, unsigned port) {
  if (!port) {
    port = 9997;
  }
  Debug::log(Debug::Info)
      << "Initiating GWT Development Mode connection to host " << host
      << ", port " << port << Debug::flush;
  return sock.connect(host, port);
}

bool HostChannel::init(SessionHandler* handler, int minProtoVers,
    int maxProtoVers, const std::string& hostedHtmlVers) {
  this->handler = handler;
  Debug::log(Debug::Debugging)
      << "  negotiating versions - we support protocol " << minProtoVers
      << " through " << maxProtoVers << ", hostedHtmlVersion=" << hostedHtmlVers
      << Debug::flush;
  // TODO(jat): support transport selection
  CheckVersionsMessage::send(*this, minProtoVers, maxProtoVers, hostedHtmlVers);
  flush();
  char type;
  if (!readByte(type)) {
    handler->fatalError(*this, "Failed to receive message type");
    Debug::log(Debug::Error) << "Failed to receive message type" << Debug::flush;
    disconnectFromHost();
    return false;
  }
  switch (type) {
    case MESSAGE_TYPE_PROTOCOL_VERSION:
    {
      scoped_ptr<ProtocolVersionMessage> imsg(ProtocolVersionMessage
          ::receive(*this));
      if (!imsg.get()) {
        Debug::log(Debug::Error) << "Failed to receive protocol version message"
            << Debug::flush;
        return false;
      }
      // TODO(jat): save selected protocol version when we support a range
      break;
    }
    case MESSAGE_TYPE_FATAL_ERROR:
    {
      scoped_ptr<FatalErrorMessage> imsg(FatalErrorMessage::receive(*this));
      if (!imsg.get()) {
        Debug::log(Debug::Error) << "Failed to receive fatal error message"
            << Debug::flush;
        return false;
      }
      handler->fatalError(*this, imsg.get()->getError());
      return false;
    }
    default:
      return false;
  }
  return true;
}

bool HostChannel::disconnectFromHost() {
  Debug::log(Debug::Debugging) << "Disconnecting channel" << Debug::flush;
  if (!isConnected()) {
    Debug::log(Debug::Error) << "Disconnecting already disconnected channel" << Debug::flush;
    return false;
  }
  QuitMessage::send(*this);
  flush();
  sock.disconnect();
  return true;
}

bool HostChannel::readInt(int32_t& data) {
  int32_t d;
  if (!readBytes(&d, sizeof(d))) return false;
  data = ntohl(d);
  return true;
}

bool HostChannel::sendInt(int32_t data) {
  uint32_t d = htonl(data);
  return sendBytes(&d, sizeof(d));
}

bool HostChannel::readShort(short& data) {
  int16_t d;
  if (!readBytes(&d, sizeof(d))) return false;
  data = ntohs(d);
  return true;
}

bool HostChannel::sendShort(const short data) {
  uint16_t d = htons(data);
  return sendBytes(&d, sizeof(d));
}

bool HostChannel::readLong(int64_t& data) {
  // network is big-endian
  int32_t d[2];
  if (!readInt(d[0])) return false;
  if (!readInt(d[1])) return false;
  data = (static_cast<int64_t>(d[0]) << 32) | ntohl(d[1]);
  return true;
}

bool HostChannel::sendLong(const int64_t data) {
  if (!sendInt(static_cast<int32_t>(data >> 32))) {
    return false;
  }
  return sendInt(static_cast<int32_t>(data));
}

bool HostChannel::readFloat(float& data) {
  char bytes[sizeof(data)];
  if (!readBytes(bytes, sizeof(bytes))) {
    return false;
  }
  data = byteOrder.floatFromBytes(bytes);
  return true;
}

bool HostChannel::sendFloat(const float data) {
  char bytes[sizeof(data)];
  byteOrder.bytesFromFloat(data, bytes);
  return sendBytes(bytes, sizeof(bytes));
}

bool HostChannel::readDouble(double& data) {
  char bytes[sizeof(data)];
  if (!readBytes(bytes, sizeof(bytes))) {
    return false;
  }
  data = byteOrder.doubleFromBytes(bytes);
  return true;
}

bool HostChannel::sendDouble(const double data) {
  char bytes[sizeof(data)];
  byteOrder.bytesFromDouble(data, bytes);
  return sendBytes(bytes, sizeof(bytes));
}

bool HostChannel::readStringLength(uint32_t& data) {
  int32_t val;
  if (!readInt(val)) return false;
  // TODO: assert positive?
  data = val;
  return true;
}

bool HostChannel::readStringBytes(char* data, const uint32_t len) {
  return readBytes(data, len);
}

bool HostChannel::readString(std::string& strRef) {
  uint32_t len;
  if (!readStringLength(len)) {
    Debug::log(Debug::Error) << "readString: failed to read length"
        << Debug::flush;
    return false;
  }
  // Allocating variable-length arrays on the stack is a GCC feature,
  // and is vulnerable to stack overflow attacks, so we allocate on the heap.
  scoped_array<char> buf(new char[len]);
  if (!readStringBytes(buf.get(), len)) {
    Debug::log(Debug::Error) << "readString: failed to read " << len
        << " bytes" << Debug::flush;
    return false;
  }
  strRef.assign(buf.get(), len);
  return true;
}

static inline double operator-(const struct timeval& end,
    const struct timeval& begin) {
  double us = end.tv_sec * 1000000.0 + end.tv_usec - begin.tv_sec * 1000000.0
      - begin.tv_usec;
  return us;
}

ReturnMessage* HostChannel::reactToMessages(SessionHandler* handler, bool expectReturn) {
  char type;
  while (true) {
    flush();
    Debug::log(Debug::Spam) << "Waiting for response, flushed output"
        << Debug::flush;
    if (!readByte(type)) {
      if (isConnected()) {
        Debug::log(Debug::Error) << "Failed to receive message type"
            << Debug::flush;
      }
      return 0;
    }
    switch (type) {
      case MESSAGE_TYPE_INVOKE:
        {
          scoped_ptr<InvokeMessage> imsg(InvokeMessage::receive(*this));
          if (!imsg.get()) {
            Debug::log(Debug::Error) << "Failed to receive invoke message" << Debug::flush;
            return 0;
          }
          Value returnValue;
          bool exception = handler->invoke(*this, imsg->getThis(), imsg->getMethodName(),
              imsg->getNumArgs(), imsg->getArgs(), &returnValue);
          handler->sendFreeValues(*this);
          ReturnMessage::send(*this, exception, returnValue);
        }
        break;
      case MESSAGE_TYPE_INVOKESPECIAL:
        {
          // scottb: I think this is never used; I think server never sends invokeSpecial
          scoped_ptr<InvokeSpecialMessage> imsg(InvokeSpecialMessage::receive(*this));
          if (!imsg.get()) {
            Debug::log(Debug::Error) << "Failed to receive invoke special message" << Debug::flush;
            return 0;
          }
          Value returnValue;
          bool exception = handler->invokeSpecial(*this, imsg->getDispatchId(),
              imsg->getNumArgs(), imsg->getArgs(), &returnValue);
          handler->sendFreeValues(*this);
          ReturnMessage::send(*this, exception, returnValue);
        }
        break;
      case MESSAGE_TYPE_FREEVALUE:
        {
          scoped_ptr<FreeValueMessage> freeMsg(FreeValueMessage::receive(*this));
          if (!freeMsg.get()) {
            Debug::log(Debug::Error) << "Failed to receive free value message" << Debug::flush;
            return 0;
          }
          handler->freeValue(*this, freeMsg->getIdCount(), freeMsg->getIds());
        }
        // do not send a response
        break;
      case MESSAGE_TYPE_LOADJSNI:
        {
          scoped_ptr<LoadJsniMessage> loadMsg(LoadJsniMessage::receive(*this));
          if (!loadMsg.get()) {
            Debug::log(Debug::Error) << "Failed to receive load JSNI message" << Debug::flush;
            return 0;
          }
          handler->loadJsni(*this, loadMsg->getJs());
        }
        // do not send a response
        break;
      case MESSAGE_TYPE_RETURN:
        if (!expectReturn) {
          Debug::log(Debug::Error) << "Received unexpected RETURN" << Debug::flush;
        }
        return ReturnMessage::receive(*this);
      case MESSAGE_TYPE_QUIT:
        if (expectReturn) {
          Debug::log(Debug::Error) << "Received QUIT while waiting for return" << Debug::flush;
        }
    	  disconnectFromHost();
        return 0;
      default:
        // TODO(jat): error handling
        Debug::log(Debug::Error) << "Unexpected message type " << type
            << ", expectReturn=" << expectReturn << Debug::flush;
        disconnectFromHost();
        return 0;
    }
  }
}

bool HostChannel::readValue(Value& valueRef) {
  char typeBuf;
  if (!readByte(typeBuf)) return false;
  Value::ValueType type = Value::ValueType(typeBuf);
  switch (type) {
    case Value::NULL_TYPE:
      valueRef.setNull();
      return true;
    case Value::UNDEFINED:
      valueRef.setUndefined();
      return true;
    case Value::BOOLEAN:
      {
        char val;
        if (!readByte(val)) return false;
        valueRef.setBoolean(val != 0);
      }
      return true;
    case Value::BYTE:
      {
        char val;
        if (!readByte(val)) return false;
        valueRef.setByte(val);
      }
      return true;
    case Value::CHAR:
      {
        short val;
        if (!readShort(val)) return false;
        valueRef.setChar(val);
      }
      return true;
    case Value::SHORT:
      {
        short val;
        if (!readShort(val)) return false;
        valueRef.setShort(val);
      }
      return true;
    case Value::STRING:
      {
        std::string val;
        if (!readString(val)) return false;
        valueRef.setString(val);
      }
      return true;
    case Value::INT:
      {
        int val;
        if (!readInt(val)) return false;
        valueRef.setInt(val);
      }
      return true;
    case Value::LONG:
      {
        int64_t val;
        if (!readLong(val)) return false;
        valueRef.setLong(val);
      }
      return true;
    case Value::DOUBLE:
      {
        double val;
        if (!readDouble(val)) return false;
        valueRef.setDouble(val);
      }
      return true;
    case Value::JAVA_OBJECT:
      {
        int objId;
        if (!readInt(objId)) return false;
        valueRef.setJavaObject(objId);
      }
      return true;
    case Value::JS_OBJECT:
      {
        int val;
        if (!readInt(val)) return false;
        valueRef.setJsObjectId(val);
      }
      return true;
    default:
      Debug::log(Debug::Error) << "Unhandled value type sent from server: " << type << Debug::flush;
      break;
  }
  return false;
}

bool HostChannel::sendValue(const Value& value) {
  Value::ValueType type = value.getType();
  if (!sendByte(type)) return false;
  switch (type) {
    case Value::NULL_TYPE:
    case Value::UNDEFINED:
      // Null and Undefined only have the tag byte, no data
      return true;
    case Value::BOOLEAN:
      return sendByte(value.getBoolean() ? 1 : 0);
    case Value::BYTE:
      return sendByte(value.getByte());
    case Value::CHAR:
      return sendShort(short(value.getChar()));
    case Value::SHORT:
      return sendShort(value.getShort());
    case Value::INT:
      return sendInt(value.getInt());
    case Value::LONG:
      return sendLong(value.getLong());
    case Value::STRING:
      return sendString(value.getString());
    case Value::DOUBLE:
      return sendDouble(value.getDouble());
    case Value::FLOAT:
      return sendFloat(value.getFloat());
    case Value::JS_OBJECT:
      return sendInt(value.getJsObjectId());
    case Value::JAVA_OBJECT:
      return sendInt(value.getJavaObjectId());
    default:
      Debug::log(Debug::Error) << "Unhandled value type sent to server: " << type << Debug::flush;
      break;
  }
  return false;
}
