// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// 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 "starboard/shared/starboard/net_args.h"

#include <string>
#include <vector>

#include "starboard/common/scoped_ptr.h"
#include "starboard/socket_waiter.h"
#include "starboard/thread.h"

#ifndef NET_ARGS_PORT
#define NET_ARGS_PORT 49355
#endif

// Controls whether using IPv4 or IPv6.
#ifndef NET_ARGS_IP_VERSION
#define NET_ARGS_IP_VERSION kSbSocketAddressTypeIpv4
#endif

namespace starboard {
namespace shared {
namespace starboard {
namespace {

scoped_ptr<Socket> CreateListenSocket() {
  scoped_ptr<Socket> socket(
      new Socket(NET_ARGS_IP_VERSION, kSbSocketProtocolTcp));
  socket->SetReuseAddress(true);
  SbSocketAddress sock_addr;
  // Ip address will be set to 0.0.0.0 so that it will bind to all sockets.
  SbMemorySet(&sock_addr, 0, sizeof(SbSocketAddress));
  sock_addr.type = NET_ARGS_IP_VERSION;
  sock_addr.port = NET_ARGS_PORT;
  SbSocketError sock_err = socket->Bind(&sock_addr);

  const char kErrFmt[] = "Socket error while attempting to bind, error = %d\n";
  if (sock_err != kSbSocketOk) {
    SbLogRawFormatF(kErrFmt, sock_err);
  }
  sock_err = socket->Listen();
  if (sock_err != kSbSocketOk) {
    SbLogRawFormatF(kErrFmt, sock_err);
  }
  return socket.Pass();
}

void WaitUntilReadableOrConnectionReset(SbSocket sock) {
  SbSocketWaiter waiter = SbSocketWaiterCreate();

  struct F {
    static void WakeUp(SbSocketWaiter waiter, SbSocket, void*, int) {
      SbSocketWaiterWakeUp(waiter);
    }
  };

  SbSocketWaiterAdd(waiter,
                    sock,
                    NULL,
                    &F::WakeUp,
                    kSbSocketWaiterInterestRead,
                    false);  // false means one shot.

  SbSocketWaiterWait(waiter);
  SbSocketWaiterRemove(waiter, sock);
  SbSocketWaiterDestroy(waiter);
}

scoped_ptr<Socket> WaitForClientConnection(Socket* listen_sock) {
  while (true) {
    scoped_ptr<Socket> client_connection(listen_sock->Accept());
    if (client_connection) {
      return client_connection.Pass();
    }
    SbThreadSleep(kSbTimeMillisecond);
  }
}

std::vector<std::string> SplitStringByLines(const std::string& string_buff) {
  std::vector<std::string> lines;
  std::stringstream ss;
  ss << string_buff;
  for (std::string line; std::getline(ss, line);) {
    if (!line.empty()) {
      lines.push_back(line);
    }
  }
  return lines;
}

}  // namespace.

// Command line switch useful for determining if NetArgsWaitForConnection()
// should be called.
const char kNetArgsCommandSwitchWait[] = "net_args_wait_for_connection";

// Waits until.
std::vector<std::string> NetArgsWaitForPayload() {
  scoped_ptr<Socket> listen = CreateListenSocket();
  scoped_ptr<Socket> client_connection = WaitForClientConnection(listen.get());

  std::string str_buff;

  while (true) {
    char buff[128];
    int result = client_connection->ReceiveFrom(buff, sizeof(buff), NULL);
    if (result > 0) {
      str_buff.append(buff, static_cast<size_t>(result));
      continue;
    } else if (result == 0) {
      // Socket has closed.
      break;
    } else if (result < 0) {  // Handle error condition.
      SbSocketError err = client_connection->GetLastError();
      client_connection->ClearLastError();

      switch (err) {
        case kSbSocketOk: {
          SB_NOTREACHED() << "Expected error condition when return val "
                          << "is < 0.";
          continue;
        }
        case kSbSocketPending: {
          WaitUntilReadableOrConnectionReset(client_connection->socket());
          continue;
        }
        default: {
          break;
        }
      }
    }
  }
  return SplitStringByLines(str_buff);
}

}  // namespace starboard
}  // namespace shared
}  // namespace starboard
