package org.iotivity.bridge.homeserver;

import android.util.Log;

import org.iotivity.OCBridge;
import org.iotivity.OCCoreRes;
import org.iotivity.OCCred;
import org.iotivity.OCCredType;
import org.iotivity.OCCredUtil;
import org.iotivity.OCCreds;
import org.iotivity.OCDeviceInfo;
import org.iotivity.OCInterfaceMask;
import org.iotivity.OCIntrospection;
import org.iotivity.OCMain;
import org.iotivity.OCMethod;
import org.iotivity.bridge.homeserver.handler.BridgeInitHandler;
import org.iotivity.bridge.homeserver.handler.FactoryPresetsHandler;
import org.iotivity.bridge.homeserver.handler.server.GetLightRequestHandler;
import org.iotivity.bridge.homeserver.handler.server.GetRequestHandler;
import org.iotivity.bridge.homeserver.handler.server.PostLightRequestHandler;
import org.iotivity.bridge.homeserver.handler.server.PostRequestHandler;
import org.iotivity.bridge.homeserver.handler.server.PutLightRequestHandler;
import org.iotivity.bridge.homeserver.handler.server.PutRequestHandler;
import org.iotivity.bridge.homeserver.model.Bridge;
import org.iotivity.bridge.homeserver.model.Light;
import org.iotivity.bridge.homeserver.model.OCFDevice;
import org.iotivity.bridge.homeserver.model.VirtualOCFDevice;
import org.iotivity.bridge.homeserver.utils.Utils;
import org.iotivity.oc.OcBridge;
import org.iotivity.oc.OcPlatform;
import org.iotivity.OCResource;
import org.iotivity.oc.OcRemoteDevice;
import org.iotivity.oc.OcRemoteResource;
import org.iotivity.oc.OcUtils;
import org.iotivity.OCUuidUtil;
import org.iotivity.OCUuid;
import org.iotivity.OCVirtualDevice;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Properties;

public class BridgeServer {

    private static final String TAG = BridgeServer.class.getSimpleName();

    // Virtual OCF Device's unique identifier such as uuid, MEID, serial number, mac address
    public static final String LIGHT_UUID = "2b32e152-3756-4fb6-b3f2-d8db7aafe39f";
    public static final String LIGHT2_UUID = "645b5166-3efb-4021-6ba0-4db90d434838";
    public static final String CLIENT_UUID = "f2f0109f-ef7d-496a-9676-d3d87b38e52f";

    private OcPlatform ocPlatform;
    private OcBridge ocBridge ;
    private BridgeInitHandler initHandler ;

    private BridgeService service = null ;

    private Bridge bridge = null ;
    private Light light = null ;

    private ArrayList<OcRemoteDevice> pairwised_devices = new ArrayList<OcRemoteDevice>();
    private ArrayList<OCUuid> pairwised_credential_uuids = new ArrayList<OCUuid>();

    public BridgeServer(BridgeService service) {
        this.service = service;
        this.bridge = new Bridge("Energy Home Hub");

        // Note: If using a factory presets handler,
        // the factory presets handler must be set prior to calling systemInit().
        // The systemInit() function will cause the factory presets handler to
        // be called if it is set.
        OcUtils.setFactoryPresetsHandler(new FactoryPresetsHandler(this.service));

        ocPlatform = OcPlatform.getInstance();
        initHandler = new BridgeInitHandler(this.service, ocPlatform, bridge);
        ocPlatform.systemInit(initHandler);

        this.initBridgeServer();
    }

    public void initBridgeServer() {

        this.addLightVirtualOCFServer(LIGHT_UUID, "Light Switch", "rs-485");
        //this.addVirtualOCFClient(CLIENT_UUID, "Virtual OCF Client", "ocf");

        this.loadPairwisedDeviceUUIDs();
    }

    public OCUuid getBridgeDeviceId() {
        return OCCoreRes.getDeviceId(Bridge.BRIDGE_INDEX);
    }
    public void shutdown() {
        ocPlatform.systemShutdown();
    }

    public void resetBridgeServer() {
        OCMain.resetDevice(Bridge.BRIDGE_INDEX);

        // this below logic has some issue for now so don't use
        //ocPlatform.reset();
        //ocPlatform.systemShutdown();
        //ocPlatform.systemInit(initHandler);
    }

    public void resetVirtualOCFDevices() {
        int vod_count = OCBridge.getVirtualDeviceCount();
        Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");

        for (int index = 1; index <= vod_count; index++) {
            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
            if (vod != null) {
                OCBridge.removeVirtualDevice(vod.getIndex());
                OCBridge.deleteVirtualDevice(vod.getIndex()); //  Note :This includes OCMain.resetDevice(index);
                Log.d(TAG, "Virtual OCF Device [" + vod.getIndex() + "] was reset!");
            }
        }
        bridge.clearVirtualOCFDeviceList();

        /* // For test
        if(OCCoreRes.getNumDevices() > 1) {
            for (int index = 1; index <= OCCoreRes.getNumDevices(); index++) {
                OCMain.resetDevice(index);
                Log.d(TAG, "OCF Device [" + index + "] was reset!");
            }
        }*/
    }

    public void resetVirtualOCFDevice(int vod_index) {
        OCBridge.removeVirtualDevice(vod_index);
        OCBridge.deleteVirtualDevice(vod_index); // Note : This includes OCMain.resetDevice(index);
        bridge.removeVirtualOCFDevice(vod_index);
    }

    public void resetDevice(int device_index) {

        if(device_index < 0) return ;

        OCDeviceInfo info = OCCoreRes.getDeviceInfo(device_index);
        if(info == null) return ;
        if(device_index == Bridge.BRIDGE_INDEX) {
            if (info != null) {
                Log.d(TAG, "Bridge Server[" + Bridge.BRIDGE_INDEX + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
                        + " will reset");
            }
            this.resetBridgeServer();

        } else if(device_index > 0) {
            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(device_index);
            if (info != null) {
                Log.d(TAG, "Virtual OCF Server/Client[" + vod.getIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
                        + ", echoname = " + vod.getEconame() + " will reset");
            }
            this.resetVirtualOCFDevice(device_index);
        }
    }

    public void resetVirtualOCFDevice(String device_sn) {
        int vod_count = OCBridge.getVirtualDeviceCount();
        Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");
        for (int index = 1; index <= vod_count; index++) {
            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
            if (vod != null && OCUuidUtil.bytesToString(vod.getId()).equalsIgnoreCase(device_sn)) {
                this.resetVirtualOCFDevice((int)vod.getIndex());
                Log.d(TAG, "Virtual OCF Device [" + vod.getIndex() + "] was reset!");
            }
        }
    }

    /*public void loadVirtualOCFDevices() {
        int vod_count = OCBridge.getVirtualDeviceCount();
        Log.d(TAG, "Virtual OCF Device Count = [" + vod_count + "], Core Device Nums = ["+OCCoreRes.getNumDevices()+"] ");

        for(int index = 1; index <= vod_count; index++) {
            OCVirtualDevice vod = OCBridge.getVirtualDeviceInfo(index);
            if(vod != null) {
                String uuid = OCUuidUtil.bytesToString(vod.getId());

                Log.d(TAG,"OCVirtualDevice["+index+"] econame = " + vod.getEconame() +", DI = " + uuid);

                // Add VOD Data & State on memory of BridgeServer
                VirtualOCFDevice vod_data = new VirtualOCFDevice(index, vod.getName(), vod.getEconame(), uuid);
                if(OCMain.isOwnedDevice(index)) vod_data.setOwned(true);
                bridge.addOrReplaceVODList(vod_data);
            }
        }
    }*/

    public String existVirtualOCFDevice(String virtual_di, String econame) {

        for(VirtualOCFDevice vod : bridge.getVirtualOCFDeviceList()){
            if(vod.getVirtualDeviceId().equals(virtual_di) && vod.getEcoName().equals(econame)) {
                return vod.getVirtualDeviceId();
            }
        }
        return null ;
    }

    public VirtualOCFDevice addVirtualOCFDevice(String device_name, String virtual_di, String device_type, String eco_name) {

        // Add Virtual Device for Light
        OCUuid uuid = OCUuidUtil.stringToUuid(virtual_di);
        int vod_index = OCBridge.addVirtualDevice(uuid.getId(),
                eco_name, "/oic/d", device_type,  // "oic.d.virtual" automatically added by internal api implements
                device_name, "ocf.2.0.5", "ocf.res.1.3.0,ocf.sh.1.3.0");

        if (vod_index != 0) {
            Log.d(TAG, "VOD Index = " + vod_index + ", VOD Count = " + OCBridge.getVirtualDeviceCount());

            OCDeviceInfo dev_info = OCCoreRes.getDeviceInfo(vod_index);
            OCVirtualDevice vod_info = OCBridge.getVirtualDeviceInfo(vod_index);
            Log.d(TAG, "VOD Info = " + vod_info);
            if (vod_info != null) {
                Log.d(TAG, "Virtual Server[" + vod_info.getIndex() + "] "
                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_info.getId())
                        + ", Econame = " + vod_info.getEconame() + ", Name = " + dev_info.getName()
                        + " was added");


                // Add VOD Data
                VirtualOCFDevice vod = new VirtualOCFDevice(vod_index, device_name, eco_name,
                        OCUuidUtil.bytesToString(vod_info.getId()), device_type);
                vod.setDiscovered(true);
                vod.setAddedToBridge(true);
                bridge.addOrReplaceVirtualOCFDevice(vod);

                // set immutable device id for Platform Independent Identifier (piid)
                OCMain.setImmutableDeviceIdentifier(vod_index, OCUuidUtil.stringToUuid(virtual_di));
                Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
                        + ", Virtual Device Id = " + virtual_di
                        + ", Device Id = " + OCUuidUtil.uuidToString(dev_info.getDi())
                        + ", Device Piid = " + OCUuidUtil.uuidToString(dev_info.getPiid()));

                // Add OCF Virtual Device IDD
                //byte[] idd_bytes = Utils.getFileBytes("idds/virtual_ocf_device_light_IDD.cbor", activity); // example : "dummy_bridge_bridge_device_IDD.cbor"
                //OCIntrospection.setIntrospectionData(vod_index, idd_bytes);

                return vod ;
            }
        }
        return null ;
    }

    public void addVirtualDeviceResource(VirtualOCFDevice device, String resource_name, String resource_uri, String resource_type, String resource_if) {

        device.addResource(resource_name, resource_uri, resource_type, resource_if);
        int interfaceMask = Utils.interfacesStringToMask(resource_if);

        // Add Device Resource and Handler
        OCResource resource = OCMain.newResource(resource_name, resource_uri, (short)1, (long)device.getVODIndex());
        OCMain.resourceBindResourceType(resource, resource_type);
        OCMain.resourceBindResourceInterface(resource, interfaceMask);
        OCMain.resourceSetDefaultInterface(resource, interfaceMask);
        OCMain.resourceSetDiscoverable(resource, true);
        OCMain.resourceSetObservable(resource, true);
        //TODO : check if it is needed for notifying to client
        //OCMain.resourceSetPeriodicObservable(resource, 60); // seconds
        OCMain.resourceSetRequestHandler(resource, OCMethod.OC_GET, new GetRequestHandler(service, device));
        OCMain.resourceSetRequestHandler(resource, OCMethod.OC_POST, new PostRequestHandler(service, device));
        OCMain.resourceSetRequestHandler(resource, OCMethod.OC_PUT, new PutRequestHandler(service, device));
        OCMain.addResource(resource);
    }

    public void addLightVirtualOCFServer(String virtual_di, String devicename, String econame) {

        // Add Virtual Device for Light
        OCUuid uuid = OCUuidUtil.stringToUuid(virtual_di) ;
        int vod_index = OCBridge.addVirtualDevice(uuid.getId(),
                econame, "/oic/d", "oic.d.light",  // "oic.d.virtual" automatically added by internal api implements
                devicename, "ocf.2.0.5", "ocf.res.1.3.0,ocf.sh.1.3.0");

        if (vod_index != 0) {
            Log.d(TAG, "VOD Index = "+ vod_index + ", VOD Count = " + OCBridge.getVirtualDeviceCount());

            light = new Light(devicename);
            OCDeviceInfo dev_info = OCCoreRes.getDeviceInfo(vod_index);
            OCVirtualDevice vod_info = OCBridge.getVirtualDeviceInfo(vod_index);
            Log.d(TAG, "VOD Info = "+ vod_info);
            if(vod_info != null) {
                Log.d(TAG, "Virtual Server[" + vod_info.getIndex() + "] "
                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_info.getId())
                        + ", Econame = " + vod_info.getEconame() + ", Name = " + dev_info.getName()
                        + " was added");

                // Add VOD Data
                VirtualOCFDevice vod = new VirtualOCFDevice(vod_index, devicename, econame,
                        OCUuidUtil.bytesToString(vod_info.getId()), "oic.d.light");
                vod.setDiscovered(true);
                vod.setAddedToBridge(true);
                bridge.addOrReplaceVirtualOCFDevice(vod);

                // Add Light Device Resources and Handler
                OCResource res_light = OCMain.newResource(devicename, "/light", (short)1, (long) vod_index);
                OCMain.resourceBindResourceType(res_light, "oic.r.switch.binary");  // BinarySwitch Resource Type
                OCMain.resourceBindResourceInterface(res_light, OCInterfaceMask.RW);
                OCMain.resourceSetDefaultInterface(res_light, OCInterfaceMask.RW);
                OCMain.resourceSetDiscoverable(res_light, true);
                OCMain.resourceSetObservable(res_light, true);
                //TODO : check if it is needed for notifying to client
                //OCMain.resourceSetPeriodicObservable(res_light, 60); // seconds
                OCMain.resourceSetRequestHandler(res_light, OCMethod.OC_GET, new GetLightRequestHandler(service, light));
                OCMain.resourceSetRequestHandler(res_light, OCMethod.OC_POST, new PostLightRequestHandler(service, light));
                OCMain.resourceSetRequestHandler(res_light, OCMethod.OC_PUT, new PutLightRequestHandler(service, light));
                OCMain.addResource(res_light);

                // Add Dimming Resource
                OCResource res_dimming = OCMain.newResource(devicename, "/dimming", (short) 1, (long) vod_index);
                OCMain.resourceBindResourceType(res_dimming, "oic.r.light.dimming");
                OCMain.resourceBindResourceInterface(res_dimming, OCInterfaceMask.RW);
                OCMain.resourceSetDefaultInterface(res_dimming, OCInterfaceMask.RW);
                OCMain.resourceSetDiscoverable(res_dimming, true);
                OCMain.resourceSetObservable(res_dimming, true);
                //TODO : check if it is needed for notifying to client
                //OCMain.resourceSetPeriodicObservable(res_dimming, 60); // seconds
                OCMain.resourceSetRequestHandler(res_dimming, OCMethod.OC_GET, new GetLightRequestHandler(service, light));
                OCMain.resourceSetRequestHandler(res_dimming, OCMethod.OC_POST, new PostLightRequestHandler(service, light));
                OCMain.resourceSetRequestHandler(res_dimming, OCMethod.OC_PUT, new PutLightRequestHandler(service, light));
                OCMain.addResource(res_dimming);


                // set immutable device id for Platform Independent Identifier (piid)
                OCMain.setImmutableDeviceIdentifier(vod_index, OCUuidUtil.stringToUuid(virtual_di));
                Log.d(TAG, "Virtual Server [" + vod_info.getIndex() + "] "
                        + ", Virtual Device Id = " + virtual_di
                        + ", Device Id = " + OCUuidUtil.uuidToString(dev_info.getDi())
                        + ", Device Piid = " + OCUuidUtil.uuidToString(dev_info.getPiid()));

                // Add Light OCF Device IDD
                byte[] idd_bytes = getFileBytes("idds/virtual_ocf_device_light_IDD.cbor"); // example : "virtual_ocf_device_light_IDD.cbor"
                OCIntrospection.setIntrospectionData(vod_index, idd_bytes);
            }
        }
    }

    public void removeLightVirtualOCFDevice(int vod_index) {

        OCVirtualDevice vod_light = OCBridge.getVirtualDeviceInfo(vod_index);
        if(vod_light != null) {
            Log.d(TAG, "Virtual Server[" + vod_light.getIndex() + "] "
                    + ", DeviceId = " + OCUuidUtil.bytesToString(vod_light.getId())
                    + ", Econame = " + vod_light.getEconame() + ", Name = " + vod_light.getEconame()
                    + " will be removed");

            int ret = OCBridge.removeVirtualDevice(vod_index);
            if (ret >=0) {
                bridge.removeVirtualOCFDevice(vod_index);
            }
        }
    }

    public void addVirtualOCFClient(String device_uuid, String devicename, String econame) {

        // Add Virtual Device for Legarcy Client like such as zibee coodinater
        OCUuid uuid = OCUuidUtil.stringToUuid(device_uuid) ;
        int vod_index = OCBridge.addVirtualDevice(uuid.getId(),
                econame, "/oic/d", "oic.d.virtualclient",  // "oic.d.virtual" automatically added by internal api implements
                devicename, "ocf.2.0.5", "ocf.res.1.3.0,ocf.sh.1.3.0");

        if(vod_index != 0) {
            OCDeviceInfo dev_info = OCCoreRes.getDeviceInfo(vod_index);
            OCVirtualDevice vod_client = OCBridge.getVirtualDeviceInfo(vod_index);
            if(vod_client != null){
                Log.d(TAG, "Virtual Client[" + vod_client.getIndex() + "] "
                        + " DeviceId = " + OCUuidUtil.bytesToString(vod_client.getId())
                        + ", Econame = " + vod_client.getEconame() + ", Name = " + dev_info.getName()
                        + " was added");

                // Add VOD Data
                VirtualOCFDevice vod = new VirtualOCFDevice(vod_index, dev_info.getName(), vod_client.getEconame(),
                        OCUuidUtil.bytesToString(vod_client.getId()), "oic.d.virtualclient");
                vod.setDiscovered(true);
                vod.setAddedToBridge(true);
                bridge.addOrReplaceVirtualOCFDevice(vod);
            }
        }

    }

    public ArrayList<VirtualOCFDevice> getVirtualOCFDeviceList() {
        return bridge.getVirtualOCFDeviceList();
    }

    public VirtualOCFDevice getVirtualOCFDevice(int vod_index) {
        return bridge.getVirtualOCFDevice(vod_index);
    }

    public VirtualOCFDevice getVirtualOCFDevice(String vod_id) {
        return bridge.getVirtualOCFDevice(vod_id);
    }

    public boolean isOwnedVirtualOCFDevice(int vod_index) {
        return OCMain.isOwnedDevice(vod_index);
    }

    public boolean addOrUpdateVirtualOCFDeviceProperties (String device_sn, String uri, String props) {
        VirtualOCFDevice device = getVirtualOCFDevice(device_sn);
        if(device != null) {
            device.addProperties(uri, props);
            return true ;
        }
        return false ;
    }

    public String getVirtualOCFDeviceProperties(String device_sn, String uri) {
        VirtualOCFDevice device = getVirtualOCFDevice(device_sn);
        if(device != null) {
            return device.getProperties(uri);
        }
        return null ;
    }


    /*
    private boolean checkExistVOD(String device_unique_id) {
        String device_uuid = existVirtualOCFDevice(devicename, econame);
        if (device_uuid == null) { // In case of no exist device
            // generate new UUID
            OCUuid new_uuid = OCUuidUtil.generateUuid();
            device_uuid = OCUuidUtil.uuidToString(new_uuid);
            Log.d(TAG, "Virtual Device : Name = " + devicename + ", DeviceId = " + device_uuid
                    + ", echoname = " + econame + " will be added since it doesn't exist.");

            return false ;
        } else {
            Log.d(TAG, "Virtual Device : Name = " + devicename + ", DeviceId = " + device_uuid
                    + ", echoname = " + econame + " exists already.");
            return true ;
        }
    }*/

    public void disconnectVirtualDevice(int vod_index) {

        Log.d(TAG, "disconnectVirtualDevice vod_index = "+vod_index+") called.");
        VirtualOCFDevice vod = bridge.getVirtualOCFDevice(vod_index);
        if (vod != null) {
            vod.setDiscovered(false);
            vod.setAddedToBridge(false);

            OCDeviceInfo info = OCCoreRes.getDeviceInfo(vod_index);
            if(OCBridge.removeVirtualDevice(vod_index) == 0) {
                Log.d(TAG, "Virtual OCF Server/Client[" + vod.getVODIndex() + "] DeviceId = " + OCUuidUtil.uuidToString(info.getDi())
                        + ", echoname = " + vod.getEcoName() + " was removed from the bridge");
            } else {
                Log.d(TAG, "Failed to remove Virtual OCF Server/Client["+vod_index+"] "+info.getName()+" from the bridge");
            }
        }
    }

    public void discoveredOCFDevice(OcRemoteDevice remoteDevice) {
        // TODO : check if discovered OCF Device has to add to the bridge as a Virtual OCF Device or not

    }

    /* These APIs are related to online pairwised devices */
    public ArrayList<OcRemoteDevice> getPairwisedDevices() {
        return pairwised_devices;
    }

    public void clearPairwisedDevices() {
        pairwised_devices.clear();
    }

    public boolean addOrReplacePairwisedDevice(OcRemoteDevice new_dev) {
        for(OcRemoteDevice dev : pairwised_devices) {
            if(OCUuidUtil.isEqual(dev.getDeviceId(), new_dev.getDeviceId())) {
                return true ;
            }
        }
        return this.pairwised_devices.add(new_dev);
    }

    public boolean removePairwisedDevices(OcRemoteDevice dev) {
        return this.pairwised_devices.remove(dev);
    }

    public boolean removePairwisedDevices(int index) {
        return pairwised_devices.remove(pairwised_devices.get(index));
    }

    public OcRemoteDevice getPairwisedDevice(int index) {
        return pairwised_devices.get(index);
    }

    public OcRemoteDevice getPairwisedDevice(String device_uuid) {
        OCUuid uuid = OCUuidUtil.stringToUuid(device_uuid);
        for(OcRemoteDevice device : pairwised_devices) {
            if(OCUuidUtil.isEqual(device.getDeviceId(), uuid)) {
                return device ;
            }
        }
        return null ;
    }

    public OcRemoteResource getPairwisedResource(String device_uuid, String resource_uri) {
        OcRemoteDevice device = getPairwisedDevice(device_uuid);
        for(OcRemoteResource resource : device.getResources()) {
            if(resource.getUri().equals(resource_uri)) {
                return resource ;
            }
        }
        return null ;
    }

    /* These APIs are related to pairwised devices by OBT at least once */
    public ArrayList<OCUuid> getPairwisedCredentialUUIDs() {
        return pairwised_credential_uuids;
    }

    public void clearPairwisedCredentialUUIDs() {
        pairwised_credential_uuids.clear();
    }

    public boolean addOrReplacePairwisedCredentialUUIDs(OCUuid new_uuid) {
        for(OCUuid uuid : pairwised_credential_uuids) {
            if(OCUuidUtil.isEqual(uuid, new_uuid)) {
                return true ;
            }
        }
        return this.pairwised_credential_uuids.add(new_uuid);
    }

    public boolean removePairwisedCredentialUUIDs(OCUuid uuid) {
        return this.pairwised_credential_uuids.remove(uuid);
    }

    public boolean removePairwisedCredentialUUIDs(int index) {
        return pairwised_credential_uuids.remove(pairwised_credential_uuids.get(index));
    }

    public OCUuid getPairwisedCredentialUUIDs(int index) {
        return pairwised_credential_uuids.get(index);
    }

    public void loadPairwisedDeviceUUIDs() {

        OCCreds creds = OCCredUtil.getCreds(Bridge.BRIDGE_INDEX);
        OCCred cred = creds.getCredsListHead() ;
        while(cred!= null) {
            if(cred.getCredType() == OCCredType.OC_CREDTYPE_PSK && !cred.getOwnerCred()) {
                OCUuid uuid = cred.getSubjectUuid();
                this.addOrReplacePairwisedCredentialUUIDs(uuid);
            }
            cred = cred.getNext();
        }

        for(OCUuid uuid : getPairwisedCredentialUUIDs()) {
            Log.d(TAG, "loadPairwisedDevices : Subject UUID = " + OCUuidUtil.uuidToString(uuid));
        }
    }

    public boolean hasPairwisedDeviceUUIDs(OCUuid uuid) {
        for(OCUuid has : getPairwisedCredentialUUIDs()) {
            if(OCUuidUtil.isEqual(has, uuid)) {
                return true ;
            }
        }
        return false ;
    }

    private byte[] getFileBytes(String filepath) {

        ByteArrayOutputStream baos = null;
        try {
            InputStream is = service.getAssets().open(filepath);
            Log.d(TAG, "reading file " + filepath);

            try {
                byte[] buffer = new byte[8192];
                baos = new ByteArrayOutputStream();
                int length = 0;
                while ((length = is.read(buffer)) != -1) {
                    Log.d(TAG, "bytes read = " + length);
                    baos.write(buffer, 0, length);
                }
            } catch (IOException e) {
                Log.e(TAG, "Error reading file " + filepath);
            } finally {
                try {
                    if (baos != null) {
                        baos.close();
                    }
                } catch (IOException e) {
                    // ignore
                }
                try {
                    if (is != null) {
                        is.close();
                    }
                } catch (IOException e) {
                    // ignore
                }
            }

        } catch (IOException e) {
            Log.e(TAG, "Failed to read " + filepath);
        }

        return ((baos != null) ? baos.toByteArray() : null);
    }
}


