package ttk.commands;

import device.Pinpad;
import tlv.TlvItem;
import ttk.Buffer;
import ttk.Session;
import ttk.Util;

import java.io.IOException;
import java.util.ArrayList;

public interface Command {
    void addToContext(TlvItem item);

    ttk.Buffer run() throws Exception;

    int getRequestID();

    void setRequestID(int requestID);

    int getErn();

    void setErn(int ern);
}

abstract class CommandBase implements Command {
    private Pinpad pinpad;
    protected ArrayList<tlv.TlvItem> context;
    protected int requestID;
    protected int ern;

    CommandBase(Pinpad pinpad) {
        this.pinpad = pinpad;
        this.context = new ArrayList<>();
        requestID = Util.generateNegativeDWORD();
        ern = Util.generateDWORD();
    }

    public void addToContext(TlvItem item) {
        context.add(item);
    }

    public int getRequestID() {
        return requestID;
    }

    public void setRequestID(int requestID) {
        this.requestID = requestID;
    }

    public int getErn() {
        return ern;
    }

    public void setErn(int ern) {
        this.ern = ern;
    }

    protected void prepare() {
    }

    private static Buffer exchange(Session ttkSession, ArrayList<TlvItem> commandContext) throws IOException {
        Buffer clientRequest = new Buffer(Buffer.MessageTypes.CLIENT_REQUEST, commandContext);
        Buffer serverAnswer;
        clientRequest.print();

        ttkSession.writeBufferToSocket(clientRequest);

        while (true) {
            serverAnswer = ttkSession.readBufFromSocket();

            if (serverAnswer != null) {
                serverAnswer.print();
                TlvItem responseCode = null;

                for (TlvItem item : serverAnswer.tagContainer) {
                    if (item.getTag().getName().equals("TAG_TTK_RESPONSE_CODE")) {
                        responseCode = item;
                        break;
                    }
                }

                if (responseCode != null)
                    return serverAnswer;
            } else {
                return null;
            }
        }
    }

    @Override
    public Buffer run() throws Exception {
        context.add(TlvItem.findItem("TAG_TTK_CLIENT_ECR", pinpad.configTlv));
        context.add(new TlvItem(tlv.Tag.findTag("TAG_TTK_CLIENT_ERN"), Util.intToUnsignedString(ern, 9)));

        //insert command specific tags
        prepare();

        context.add(new TlvItem(tlv.Tag.findTag("TAG_TTK_REQUEST_ID"), Util.makeLsbDword(requestID)));

        return exchange(pinpad.ttkSession, context);
    }
}




