package org.knowm.xchange.okcoin;

import org.knowm.xchange.BaseExchange;
import org.knowm.xchange.ExchangeSpecification;
import org.knowm.xchange.okcoin.service.OkCoinAccountService;
import org.knowm.xchange.okcoin.service.OkCoinFuturesAccountService;
import org.knowm.xchange.okcoin.service.OkCoinFuturesMarketDataService;
import org.knowm.xchange.okcoin.service.OkCoinFuturesTradeService;
import org.knowm.xchange.okcoin.service.OkCoinMarketDataService;
import org.knowm.xchange.okcoin.service.OkCoinTradeService;

import si.mazi.rescu.SynchronizedValueFactory;

public class OkCoinExchange extends BaseExchange {

  @Override
  public void applySpecification(ExchangeSpecification exchangeSpecification) {

    super.applySpecification(exchangeSpecification);

    if (exchangeSpecification.getExchangeSpecificParametersItem("Use_Intl").equals(false)
        && exchangeSpecification.getExchangeSpecificParametersItem("Use_Futures").equals(true)) {
      throw new RuntimeException("Futures only available on international version. Set `Use_Intl` to true.");
    }

    concludeHostParams(exchangeSpecification);
  }

  @Override
  protected void initServices() {

    concludeHostParams(exchangeSpecification);

    if (exchangeSpecification.getExchangeSpecificParameters() != null
        && exchangeSpecification.getExchangeSpecificParametersItem("Use_Futures").equals(true)) {
      FuturesContract contract = futuresContractOfConfig(exchangeSpecification);

      this.marketDataService = new OkCoinFuturesMarketDataService(this, contract);
      if (exchangeSpecification.getApiKey() != null) {
        this.accountService = new OkCoinFuturesAccountService(this);
        this.tradeService = new OkCoinFuturesTradeService(this, contract, futuresLeverageOfConfig(exchangeSpecification));
      }
    } else {
      this.marketDataService = new OkCoinMarketDataService(this);
      if (exchangeSpecification.getApiKey() != null) {
        this.accountService = new OkCoinAccountService(this);
        this.tradeService = new OkCoinTradeService(this);
      }
    }
  }

  /**
   * Adjust host parameters depending on exchange specific parameters
   */
  private static void concludeHostParams(ExchangeSpecification exchangeSpecification) {

    if (exchangeSpecification.getExchangeSpecificParameters() != null
        && exchangeSpecification.getExchangeSpecificParametersItem("Use_Intl").equals(true)) {
      exchangeSpecification.setSslUri("https://www.okex.com/api");
      exchangeSpecification.setHost("www.okex.com");
      exchangeSpecification.setExchangeSpecificParametersItem("Websocket_SslUri", "wss://real.okex.com:10440/websocket/okcoinapi");
    }
  }

  /**
   * Extract futures leverage used by spec
   */
  private static int futuresLeverageOfConfig(ExchangeSpecification exchangeSpecification) {

    if (exchangeSpecification.getExchangeSpecificParameters().containsKey("Futures_Leverage")) {
      return Integer.valueOf((String) exchangeSpecification.getExchangeSpecificParameters().get("Futures_Leverage"));
    } else {
      // default choice of 10x leverage is "safe" choice and default by OkCoin.
      return 10;
    }
  }

  /**
   * Extract contract used by spec
   */
  public static FuturesContract futuresContractOfConfig(ExchangeSpecification exchangeSpecification) {

    FuturesContract contract;

    if (exchangeSpecification.getExchangeSpecificParameters().containsKey("Futures_Contract")) {
      contract = (FuturesContract) exchangeSpecification.getExchangeSpecificParameters().get("Futures_Contract");
    } else if (exchangeSpecification.getExchangeSpecificParameters().containsKey("Futures_Contract_String")) {
      contract = FuturesContract.valueOfIgnoreCase(FuturesContract.class,
          (String) exchangeSpecification.getExchangeSpecificParameters().get("Futures_Contract_String"));
    } else {
      throw new RuntimeException("`Futures_Contract` or `Futures_Contract_String` not defined in exchange specific parameters.");
    }

    return contract;
  }

  @Override
  public ExchangeSpecification getDefaultExchangeSpecification() {

    ExchangeSpecification exchangeSpecification = new ExchangeSpecification(this.getClass().getCanonicalName());
    exchangeSpecification.setSslUri("https://www.okcoin.cn/api");
    exchangeSpecification.setHost("www.okcoin.cn");
    exchangeSpecification.setExchangeName("OKCoin");
    exchangeSpecification.setExchangeDescription("OKCoin is a globally oriented crypto-currency trading platform.");

    // set to true to automatically use the Intl_ parameters for ssluri and host
    exchangeSpecification.setExchangeSpecificParametersItem("Use_Intl", false);
    exchangeSpecification.setExchangeSpecificParametersItem("Use_Futures", false);

    exchangeSpecification.setExchangeSpecificParametersItem("Websocket_SslUri", "wss://real.okcoin.cn:10440/websocket/okcoinapi");

    return exchangeSpecification;
  }

  @Override
  public SynchronizedValueFactory<Long> getNonceFactory() {

    // This exchange doesn't use a nonce for authentication
    return null;
  }

  @Override
  public String getMetaDataFileName(ExchangeSpecification exchangeSpecification) {

    if (exchangeSpecification.getExchangeSpecificParametersItem("Use_Intl").equals(false)) {
      return exchangeSpecification.getExchangeName().toLowerCase().replace(" ", "").replace("-", "").replace(".", "") + "_china";
    } else {
      if (exchangeSpecification.getExchangeSpecificParametersItem("Use_Futures").equals(true)) {
        return exchangeSpecification.getExchangeName().toLowerCase().replace(" ", "").replace("-", "").replace(".", "") + "_futures";
      } else {
        return exchangeSpecification.getExchangeName().toLowerCase().replace(" ", "").replace("-", "").replace(".", "") + "_intl";
      }

    }
  }
}

@@ -2315,85 +2315,655 @@
 null
+) %7B
 %0A      
-  && exchangeSpecification.getExchangeSpecificParametersItem(%22Use_Intl
+if(exchangeSpecification.getExchangeSpecificParametersItem(%22Use_Intl%22).equals(true) &&%0A              exchangeSpecification.getExchangeSpecificParametersItem(%22Use_Futures%22).equals(false)) %7B%0A%0A        exchangeSpecification.setSslUri(%22https://www.okcoin.com/api%22);%0A        exchangeSpecification.setHost(%22www.okcoin.com%22);%0A        exchangeSpecification.setExchangeSpecificParametersItem(%22Websocket_SslUri%22, %22wss://real.okcoin.com:10440/websocket/okcoinapi%22);%0A%0A      %7D else if(exchangeSpecification.getExchangeSpecificParametersItem(%22Use_Intl%22).equals(true) &&%0A              exchangeSpecification.getExchangeSpecificParametersItem(%22Use_Futures
 %22).e
@@ -2973,24 +2973,27 @@
 ls(true)) %7B%0A
+%0A  
       exchan
@@ -3045,32 +3045,34 @@
 om/api%22);%0A      
+  
 exchangeSpecific
@@ -3098,24 +3098,26 @@
 okex.com%22);%0A
+  
       exchan
@@ -3231,24 +3231,33 @@
 okcoinapi%22);
+%0A%0A      %7D
 %0A    %7D%0A  %7D%0A%0A

Fix wrong config distinction between international and international futures only