/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you 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.
 */
#ifndef _THRIFT_TEST_SERVERTHREAD_H_
#define _THRIFT_TEST_SERVERTHREAD_H_ 1

#include <thrift/TProcessor.h>
#include <thrift/protocol/TProtocol.h>
#include <thrift/server/TServer.h>
#include <thrift/transport/TTransport.h>

#include "EventLog.h"

namespace apache {
namespace thrift {
namespace test {

/**
 * A helper class to tell ServerThread how to create the server
 */
class ServerState {
public:
  virtual ~ServerState() = default;

  /**
   * Create a server to listen on the specified port.
   *
   * If the server returned fails to bind to the specified port when serve() is
   * called on it, createServer() may be called again on a different port.
   */
  virtual std::shared_ptr<server::TServer> createServer(uint16_t port) = 0;

  /**
   * Get the TServerEventHandler to set on the server.
   *
   * This is only called after the server successfully binds and is about to
   * start serving traffic.  It is invoked from the server thread, rather than
   * the main thread.
   */
  virtual std::shared_ptr<server::TServerEventHandler> getServerEventHandler() {
    return std::shared_ptr<server::TServerEventHandler>();
  }

  /**
   * This method is called in the server thread after server binding succeeds.
   *
   * Subclasses may override this method if they wish to record the final
   * port that was used for the server.
   */
  virtual void bindSuccessful(uint16_t /*port*/) {}
};

/**
 * ServerThread starts a thrift server running in a separate thread.
 */
class ServerThread {
public:
  ServerThread(const std::shared_ptr<ServerState>& state, bool autoStart)
    : port_(0),
      running_(false),
      serving_(false),
      error_(false),
      serverState_(state) {
    if (autoStart) {
      start();
    }
  }

  void start();
  void stop();

  uint16_t getPort() const { return port_; }

  ~ServerThread() {
    if (running_) {
      try {
        stop();
      } catch (...) {
        GlobalOutput.printf("error shutting down server");
      }
    }
  }

protected:
  // Annoying.  thrift forces us to use shared_ptr, so we have to use
  // a helper class that we can allocate on the heap and give to thrift.
  // It would be simpler if we could just make Runnable and TServerEventHandler
  // private base classes of ServerThread.
  class Helper : public concurrency::Runnable, public server::TServerEventHandler {
  public:
    Helper(ServerThread* serverThread) : serverThread_(serverThread) {}

    void run() override { serverThread_->run(); }

    void preServe() override { serverThread_->preServe(); }

  private:
    ServerThread* serverThread_;
  };

  void run();
  void preServe();

  std::shared_ptr<Helper> helper_;

  uint16_t port_;
  bool running_;
  bool serving_;
  bool error_;
  concurrency::Monitor serverMonitor_;

  std::shared_ptr<ServerState> serverState_;
  std::shared_ptr<server::TServer> server_;
  std::shared_ptr<concurrency::Thread> thread_;
};
}
}
} // apache::thrift::test

#endif // _THRIFT_TEST_SERVERTHREAD_H_
