// Copyright (c) 2010-2011, MarketFactory Inc. All rights reserved.
#include <API/Clients/CPP/AbstractMFHandler.h>
#include <API/Clients/CPP/MFClient.h>
#include <API/Clients/CPP/MFInit.h>
#include <API/Clients/CPP/Proto/APIAll.h>

#include <cstdlib>
#include <iostream>

using namespace MFAPI;
namespace {

#define TEST_LOG(X) std::cout << X << std::endl;

// A very basic sample handler that subscribes to some market data and prints
// the updates.

class BatchHandler : public AbstractMFHandler {
  virtual void onStart(MFClient& client) {
    TEST_LOG("CONNECT");

    // Subscribe to some market data feed (for example).
    // const APIFeed* feed = client.getFeedByName("EBS-AI");
    const APIFeed* feed = client.getFeedByID(99);

    if (!feed) {
      TEST_LOG("Could not get HOTSPOT feed");
      client.stop();
      return;
    }

    // Find the four markets that we're interested in.
    const APIMarket* mUsdJpy = client.getMarketByName(*feed, "USD/JPY");
    const APIMarket* mEurUsd = client.getMarketByName(*feed, "EUR/USD");
    const APIMarket* mUsdCad = client.getMarketByName(*feed, "USD/CAD");
    const APIMarket* mUsdChf = client.getMarketByName(*feed, "USD/CHF");

    // Subscribe to market data updates for all the markets.
    client.subscribeMD(feed->feedID, mUsdJpy->marketID);
    client.subscribeMD(feed->feedID, mEurUsd->marketID);
    client.subscribeMD(feed->feedID, mUsdCad->marketID);
    client.subscribeMD(feed->feedID, mUsdChf->marketID);

    // Register for batch complete messages for a pair of markets.
    int marketIds1[2] = {mUsdJpy->marketID, mUsdCad->marketID};
    int bd1 = client.registerMarketComb(feed->feedID, marketIds1, 2).second;
    TEST_LOG("BATCH1 ID = " << bd1);

    // Register for batch complete messages for another pair of markets.
    int marketIds2[3] = {mEurUsd->marketID, mUsdCad->marketID,
                         mUsdChf->marketID};
    int bd2 = client.registerMarketComb(feed->feedID, marketIds2, 3).second;
    TEST_LOG("BATCH2 ID = " << bd2);
  }

  virtual void onStop(MFClient& client) {}

  virtual void onDisconnect(MFClient& client) {}

  virtual void onConnect(MFClient& client) {}

  virtual void onHeartbeat(const Heartbeat& heartbeat, MFClient& client) {}

  virtual void onSubscriptionEvent(const SubscriptionEvent& subscriptionEvent,
                                   MFClient& client) {
    TEST_LOG("SUB = " << subscriptionEvent);
  }

  virtual void onMarketData(const MarketView& marketData, MFClient& client) {
    TEST_LOG("MD = " << marketData);
  }

  virtual void onEventReport(const EventReport& eventReport, MFClient& client) {
    TEST_LOG("EV = " << eventReport);
  }

  virtual void onDateRollover(const DateRollover& dateRollover,
                              MFClient& client) {
    TEST_LOG("EV = " << dateRollover);
  }

  virtual void onBatchComplete(int batchDefID, MFClient& client) {
    TEST_LOG("BA = " << batchDefID);
  }

  virtual void onOrderReceived(const OrderReceived& orderReceived,
                               MFClient& client) {
    TEST_LOG("OR = " << orderReceived);
  }

  virtual void onOrderRejected(const OrderRejected& orderRejected,
                               MFClient& client) {
    TEST_LOG("OR = " << orderRejected);
  }

  virtual void onOrderSubmitted(const OrderSubmitted& orderSubmitted,
                                MFClient& client) {
    TEST_LOG("OR = " << orderSubmitted);
  }

  virtual void onOrderCanceled(const OrderCanceled& orderCanceled,
                               MFClient& client) {
    TEST_LOG("OR = " << orderCanceled);
  }

  virtual void onOrderCancelRejected(
      const OrderCancelRejected& orderCancelRejected, MFClient& client) {
    TEST_LOG("OR = " << orderCancelRejected);
  }

  virtual void onTradeCapture(const TradeCapture& tradeCapture,
                              MFClient& client) {
    TEST_LOG("TC = " << tradeCapture);
  }

  virtual void onOrderDone(const OrderDone& orderDone, MFClient& client) {
    TEST_LOG("OR = " << orderDone);
  }

  virtual void onDropCopy(const DropCopy& dropCopy, MFClient& client) {
    TEST_LOG("DC = " << dropCopy);
  }
};
}

int main(int argc, char** argv) {
  // Initialize the library.
  MFInit::initialize();

  try {

    const char* hostname = "demo.marketfactory.com";
    int port = 80;

    if (argc >= 2) {
      hostname = argv[1];
    }

    if (argc >= 3) {
      port = atoi(argv[2]);
    }

    TEST_LOG("host: " << hostname);
    TEST_LOG("port: " << port);

    // Connect a client.
    MFClient* client = MFClient::open(
        "CHANGE_TO_YOUR_MARKET_FACTORY_PORTAL_USERNAME",
        "CHANGE_TO_YOUR_MARKET_FACTORY_PORTAL_PASSWORD", hostname, port);
    if (client == 0) {
      std::cerr << "Could not connect." << std::endl;
      return 1;
    }

    // Create a handler instance.
    BatchHandler handler;

    // Dispatch the messages on it (returns when stop() is called).
    client->run(&handler);
    TEST_LOG("out = ");
  }
  catch (const std::exception& e) {
    std::cerr << "Error: " << e.what() << std::endl;
  }

  // Finalize the library.
  MFInit::finalize();
  return 0;
}
