package quantisan.qte_lmax;

import com.lmax.api.FailureResponse;
import com.lmax.api.FixedPointNumber;
import com.lmax.api.Session;
import com.lmax.api.TimeInForce;
import com.lmax.api.order.MarketOrderSpecification;
import com.lmax.api.order.OrderCallback;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import us.bpsm.edn.parser.Parseable;
import us.bpsm.edn.parser.Parser;
import us.bpsm.edn.parser.Parsers;

import java.util.Map;

import static us.bpsm.edn.Keyword.newKeyword;
import static us.bpsm.edn.parser.Parsers.defaultConfiguration;

public class Order {
    final static Logger logger = LoggerFactory.getLogger(Order.class);

    private final Session session;
    private final MarketOrderSpecification marketOrderSpecification;

    public enum OrderState { NONE, FAIL, PENDING };
    private OrderState orderState = OrderState.NONE;

    /**
     * Parse a EDN message to a market order.
     *
     * @param ednMessage a EDN message
     * @return a market order
     */
    public static MarketOrderSpecification toMarketOrder(String ednMessage) {
        Parseable pbr = Parsers.newParseable(ednMessage);
        Parser p = Parsers.newParser(defaultConfiguration());
        Map<?, ?> m = (Map<?, ?>) p.nextValue(pbr);
        String orderId = m.get(newKeyword("order-id")).toString();
        Long instrument = Instrument.toId(m.get(newKeyword("instrument")).toString());
        FixedPointNumber quantity = FixedPointNumber.valueOf((Long)m.get(newKeyword("quantity")));

        FixedPointNumber stopLossOffset = FixedPointNumber.valueOf((Long)m.get(newKeyword("stop-loss-offset")));

        return new MarketOrderSpecification(instrument, orderId, quantity, TimeInForce.IMMEDIATE_OR_CANCEL,stopLossOffset, null);
    }

    public Order(Session session, String message) {
        this.session = session;
        this.marketOrderSpecification = toMarketOrder(message);
    }

    public void execute() {
        if (getOrderState() == OrderState.NONE) {
            session.placeMarketOrder(this.marketOrderSpecification, new OrderCallback()
            {
                public void onSuccess(String placeOrderInstructionId)
                {
                    // note - this will be the same instructionId from above,
                    // it confirms this success is related to that specific place order request

                    //move from "new" to "pending" to show the order was successfully placed
                    logger.info("Order sent and pending: {}", placeOrderInstructionId);
                    setOrderState(OrderState.PENDING);
                }

                public void onFailure(FailureResponse failureResponse)
                {
                    setOrderState(OrderState.FAIL);
                    logger.error("Failed to place order: {}", failureResponse);
                }
            });
        }
    }

    public MarketOrderSpecification getMarketOrderSpecification() {
        return marketOrderSpecification;
    }

    public OrderState getOrderState() {
        return orderState;
    }

    public void setOrderState(OrderState orderState) {
        this.orderState = orderState;
    }
}

@@ -2744,105 +2744,964 @@
 L);%0A
-                    logger.error(%22Failed to place order: %7B%7D%22, failureResponse);%0A                %7D
+%0A                    if (!failureResponse.isSystemFailure())%0A                    %7B%0A                        logger.error(%22Order data error - Message: %7B%7D, Description: %7B%7D%22,%0A                                failureResponse.getMessage(),%0A                                failureResponse.getDescription());%0A                    %7D%0A                    else%0A                    %7B%0A                        Exception e = failureResponse.getException();%0A                        if (e != null)%0A                        %7B%0A                            logger.error(%22Order exception raised - %22, e);%0A                        %7D%0A                        else%0A                        %7B%0A                            logger.error(%22Order system error - Message: %7B%7D, Description: %7B%7D%22,%0A                                    failureResponse.getMessage(),%0A                                    failureResponse.getDescription());%0A                        %7D%0A                    %7D%0A                %7D%0A
 %0A   

handle order onfailure