package org.iotivity.onboardingtool;

import android.util.Log;

import org.iotivity.OCFactoryPresetsHandler;
import org.iotivity.OCPki;
import org.iotivity.oc.OcObt;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

public class FactoryPresetsHandler implements OCFactoryPresetsHandler {

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

    private OnBoardingActivity activity;

    public FactoryPresetsHandler(OnBoardingActivity activity) {
        this.activity = activity;
    }

    @Override
    public void handler(long deviceIndex) {
        Log.d(TAG, "inside the FactoryPresetsHandler, deviceIndex  = " + deviceIndex);

        // Shutdown and re-init instance
        if (activity.getObt() != null) {
            activity.getObt().shutdown();
        }
        activity.ownedDeviceList.clear();
        activity.unownedDeviceList.clear();
        activity.setObt(new OcObt());

        setPKISecurityMfgCert(deviceIndex);
    }

    private void setPKISecurityMfgCert(long deviceIndex) {

        // load End Endtity cert
        byte[] cert = getFileBytes("pki_certs/ocf/ee.pem");
        if (cert == null) {
            Log.e(TAG, "Failed to read certificates");
            return;
        }

        // load End Endtity private key
        byte[] key = getFileBytes("pki_certs/ocf/key.pem");
        if (key == null) {
            Log.e(TAG, "Failed to read private key");
            return;
        }

        // add End Entity Cert
        int eeCredId = OCPki.addMfgCert(deviceIndex, cert, key);
        Log.d(TAG, "addMfgCert() credId = " + eeCredId);
        if (eeCredId < 0) {
            Log.e(TAG, "Error installing manufacturer ee certificate");
            return;
        }

        // load Sub CA
        byte[] subCa = getFileBytes("pki_certs/ocf/subca3.pem");
        if (subCa == null) {
            Log.e(TAG, "Failed to read sub ca cetificate");
            return;
        }
        // add Sub CA
        int subCaCredId = OCPki.addMfgIntermediateCert(deviceIndex, eeCredId, subCa);
        Log.d(TAG, "addMfgIntermediateCert() result = " + subCaCredId);
        if (subCaCredId < 0) {
            Log.e(TAG, "Error installing intermediate ca certificate");
            return;
        }

        // load Root CA 1
        byte[] rootCa1 = getFileBytes("pki_certs/rootca1.pem");
        if (rootCa1 == null) {
            Log.e(TAG, "Failed to read root ca1 certificate");
            return;
        }

        // add Root CA 1
        int rootCaCredId = OCPki.addMfgTrustAnchor(deviceIndex, rootCa1);
        Log.d(TAG, "addMfgTrustAnchor() result = " + rootCaCredId);
        if (rootCaCredId < 0) {
            Log.e(TAG, "Error installing root ca1 certificate");
            return;
        }

        /*// load Root CA 2
        byte[] rootCa2 = getFileBytes("pki_certs/rootca2.pem");
        if (rootCa2 == null) {
            Log.e(TAG, "Failed to read root ca2 certificate");
            return;
        }

        // add Root CA 2
        rootCaCredId = OCPki.addMfgTrustAnchor(deviceIndex, rootCa2);
        Log.d(TAG, "addMfgTrustAnchor() result = " + rootCaCredId);
        if (rootCaCredId < 0) {
            Log.e(TAG, "Error installing root ca2 certificate");
            return;
        }
        */
        // load Root CA 3
        byte[] rootCa3 = getFileBytes("pki_certs/rootca3.pem");
        if (rootCa3 == null) {
            Log.e(TAG, "Failed to read root ca3 certificate");
            return;
        }

        // add Root CA 3
        rootCaCredId = OCPki.addMfgTrustAnchor(deviceIndex, rootCa3);
        Log.d(TAG, "addMfgTrustAnchor() result = " + rootCaCredId);
        if (rootCaCredId < 0) {
            Log.e(TAG, "Error installing root ca3 certificate");
            return;
        }
    }

    public byte[] getFileBytes(String filepath) {

        ByteArrayOutputStream baos = null;
        try {
            InputStream is = activity.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);
        }

        if(baos!=null) {
            int len = baos.toByteArray().length ;
            byte[] result = Arrays.copyOf(baos.toByteArray(), len + 1);
            result[len] = (byte)0x00;
            Log.d(TAG, "bytes length = " + result.length);
            return result ;
        }
        return null ;
    }
}
