/*
 * Copyright (C) 2017 NXP Semiconductors
 *
 * Licensed 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.
 */
package com.android.nfc.sneptest;

import java.io.IOException;
import java.io.UnsupportedEncodingException;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.nfc.NdefMessage;
import android.os.IBinder;
import android.os.Messenger;
import android.util.Log;

import com.android.nfc.DeviceHost.LlcpSocket;
import com.android.nfc.LlcpException;
import com.android.nfc.NfcService;
import com.android.nfc.DtaServiceConnector;
import com.android.nfc.snep.SnepException;
import com.android.nfc.snep.SnepMessage;
import com.android.nfc.snep.SnepMessenger;

public final class DtaSnepClient {
    private static final String TAG = "DtaSnepClient";
    private static final boolean DBG = true;
    private static final int DEFAULT_ACCEPTABLE_LENGTH = 1024;
    private static final int DEFAULT_MIU = 128;
    private static final int DEFAULT_RWSIZE = 1;
    private static final int DEFAULT_PORT = 63;
    private static final String SNEP_SERVICE_NAME = "urn:nfc:sn:snep";
    private static final String DEFAULT_SERVICE_NAME = SNEP_SERVICE_NAME;
    private final Object mTransmissionLock = new Object();

    private int mState = DISCONNECTED;
    private final int mAcceptableLength;
    private final int mFragmentLength;
    private final int mMiu;
    private final int mPort;
    private final int mRwSize;
    private final String mServiceName;
    public static int mTestCaseId;

    private static final int DISCONNECTED = 0;
    private static final int CONNECTING = 1;
    private static final int CONNECTED = 2;

    SnepMessenger mMessenger = null;

    public DtaSnepClient() {
        mServiceName = DEFAULT_SERVICE_NAME;
        mPort = DEFAULT_PORT;
        mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
        mFragmentLength = -1;
        mMiu = DEFAULT_MIU;
        mRwSize = DEFAULT_RWSIZE;
    }

    public DtaSnepClient(String serviceName, int miu, int rwSize, int testCaseId) {
        mServiceName = serviceName;
        mPort = -1;
        mAcceptableLength = DEFAULT_ACCEPTABLE_LENGTH;
        mFragmentLength = -1;
        mMiu = miu;
        mRwSize = rwSize;
        mTestCaseId = testCaseId;
    }

    public void DtaClientOperations(Context mContext) {
        DtaServiceConnector dtaServiceConnector=new DtaServiceConnector(mContext);
        dtaServiceConnector.bindService();
        if (DBG) Log.d(TAG, "Connecting remote server");
        try {
            connect();
        } catch(IOException e) {
            Log.e(TAG, "Error connecting remote server");
        }
        switch(mTestCaseId) {
           //TC_C_BIT_BV_01
           case 1:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Small Ndef Data");
                   put(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                     e.printStackTrace();
               } catch (IOException e) {
                     e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_BIT_BI_01_0
           case 2:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Small Ndef Data");
                   put(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_BIT_BI_01_1
           case 3:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Small Ndef Data");
                   put(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_PUT_BV_01
           case 4:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Small Ndef Data");
                   put(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_PUT_BV_02
           case 5:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Large Ndef Data");
                   put(SnepMessage.getLargeNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getLargeNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_PUT_BI_01
           case 6:
           {
               try {
                   if (DBG) Log.d(TAG, "PUT Large Ndef Data");
                   put(SnepMessage.getLargeNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getLargeNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_GET_BV_01
           case 7:
           {
               try {
                   if (DBG) Log.d(TAG, "GET Ndef Message");
                   get(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_GET_BV_02
           case 8:
           {
               try {
                   if (DBG) Log.d(TAG, "GET Ndef Message");
                   get(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           //TC_C_GET_BV_03
           case 9:
           {
               try {
                   if (DBG) Log.d(TAG, "GET Ndef Message");
                   get(SnepMessage.getSmallNdef());
                   dtaServiceConnector.sendMessage(SnepMessage.getSmallNdef().toString());
               } catch (UnsupportedEncodingException e) {
                   e.printStackTrace();
               } catch (IOException e) {
                   e.printStackTrace();
               }
               close();
           }
           break;
           default:
               if (DBG) Log.d(TAG, "Unknown test case");
        }
    }

    public void put(NdefMessage msg) throws IOException {
        SnepMessenger messenger;
        synchronized (this) {
            if (mState != CONNECTED) {
                throw new IOException("Socket not connected.");
            }
            messenger = mMessenger;
        }

        synchronized (mTransmissionLock) {
            try {
                messenger.sendMessage(SnepMessage.getPutRequest(msg));
                messenger.getMessage();
            } catch (SnepException e) {
                throw new IOException(e);
            }
        }
    }

    public SnepMessage get(NdefMessage msg) throws IOException {
        SnepMessenger messenger;
        synchronized (this) {
            if (mState != CONNECTED) {
                throw new IOException("Socket not connected.");
            }
            messenger = mMessenger;
        }

        synchronized (mTransmissionLock) {
            try {
                messenger.sendMessage(SnepMessage.getGetRequest(mAcceptableLength, msg));
                return messenger.getMessage();
            } catch (SnepException e) {
                throw new IOException(e);
            }
        }
    }

    public void connect() throws IOException {
        synchronized (this) {
            if (mState != DISCONNECTED) {
                throw new IOException("Socket already in use.");
            }
            mState = CONNECTING;
        }

        LlcpSocket socket = null;
        SnepMessenger messenger;
        try {
            if (DBG) Log.d(TAG, "about to create socket");
            // Connect to the snep server on the remote side
            socket = NfcService.getInstance().createLlcpSocket(0, mMiu, mRwSize, 1024);
            if (socket == null) {
                throw new IOException("Could not connect to socket.");
            }
            if (mPort == -1) {
                if (DBG) Log.d(TAG, "about to connect to service " + mServiceName);
                socket.connectToService(mServiceName);
            } else {
                if (DBG) Log.d(TAG, "about to connect to port " + mPort);
                socket.connectToSap(mPort);
            }
            int miu = socket.getRemoteMiu();
            int fragmentLength = (mFragmentLength == -1) ?  miu : Math.min(miu, mFragmentLength);
            messenger = new SnepMessenger(true, socket, fragmentLength);
        } catch (LlcpException e) {
            synchronized (this) {
                mState = DISCONNECTED;
            }
            throw new IOException("Could not connect to socket");
        } catch (IOException e) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException e2) {}
            }
            synchronized (this) {
                mState = DISCONNECTED;
            }
            throw new IOException("Failed to connect to socket");
        }

        synchronized (this) {
            mMessenger = messenger;
            mState = CONNECTED;
        }
    }

    public void close() {
        synchronized (this) {
            if (mMessenger != null) {
               try {
                   mMessenger.close();
               } catch (IOException e) {
                   // ignore
               } finally {
                   mMessenger = null;
                   mState = DISCONNECTED;
               }
            }
        }
    }
}
