// 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/common/socket.h"
#include "starboard/socket_waiter.h"
#include "starboard/thread.h"
#include "starboard/time.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.
  memset(&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,
                                           SbTime timeout) {
  SbTimeMonotonic expire_time =
      (timeout >= 0) && (timeout < kSbTimeMax)?
      SbTimeGetMonotonicNow() + timeout :
      kSbTimeMax;
  while (true) {
    scoped_ptr<Socket> client_connection(listen_sock->Accept());
    if (client_connection) {
      return client_connection.Pass();
    }
    if (SbTimeGetMonotonicNow() > expire_time) {
      return scoped_ptr<Socket>();
    }
    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";

std::vector<std::string> NetArgsWaitForPayload(SbTime timeout) {
  scoped_ptr<Socket> listen = CreateListenSocket();
  scoped_ptr<Socket> client_connection =
      WaitForClientConnection(listen.get(), timeout);
  if (!client_connection) {
    SB_LOG(ERROR) << "Timed out waiting for net args.";
    return std::vector<std::string>();
  }

  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
