// Local imports
#include "crypto.h"
#include "rng.h"

#include <WiFi.h>
#include <WiFiClient.h>
// Energia constructors
#include "Arduino.h"

#define MLEN 32

void setup();
void loop();

char ssid[255] = {0};
char pass[255] = {0};

uint16_t ID = 1050;  // Device ID
uint16_t port = 9000;
IPAddress server(192,168,0,10);
WiFiClient wclient;

uint8_t aes_key[16] = {
        0x03, 0x02, 0x01, 0x00,
        0x07, 0x06, 0x05, 0x04,
        0x0b, 0x0a, 0x09, 0x08,
        0x0f, 0x0e, 0x0d, 0x0c
};

typedef struct {
    uint16_t ID;
    uint16_t LEN;
} header;

uint8_t AESData[MLEN], *AESResult, AESResult2[MLEN];
uint32_t AESDataLength=MLEN;

void setupWifi() {
    if(ssid[0] != 0x00) return;
    int32_t pnt = 0;
    bool typingp = false;
    Serial.print("SSID: ");
    while (1) {
        if(Serial.available() > 0) {
            if(!typingp) {
                ssid[pnt] = Serial.read();
                if(ssid[pnt] == 13) {
                    ssid[pnt] = 0x00;
                    typingp = true;
                    pnt = -1;
                    Serial.println();
                    Serial.print("PASS: ");
                }
                else Serial.write(ssid[pnt]);
            } else {
               pass[pnt] = Serial.read();
               if(pass[pnt] == 13) {
                   pass[pnt] = 0x00;
                   break;
               }
               else Serial.write(pass[pnt]);
            }
            pnt ++;
        }
    }
    Serial.println();

}

void setup() {
    // initialising
    Serial.begin(9600);

    Serial.print("Setup RNG ..");
    RNGSetup();
    Serial.println("OK");

    Serial.print("Setup AES ..");
    AESSetup(AES_KEY_128BIT, aes_key);
    Serial.println("OK");

    setupWifi();
    Serial.print("Setup WiFi ..");
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) {delay(200);}
    Serial.println("OK");
    
    Serial.print("Setup DHCP ..");
    while (WiFi.localIP() == INADDR_NONE) {delay(200);}
    Serial.print("OK ");
    Serial.println(WiFi.localIP());
    
    Serial.print("Setup Socket ..");
    while(wclient.connect(server, port) == false) {delay(200);}
    Serial.println("OK");

    //String msg = "This is secret!";
    //msg.toCharArray((char *)AESData, MLEN);
//
//    Serial.print("KEY: ");
//    for(int i=0;i<16;i++) {
//        Serial.print(aes_key[i], HEX);
//        Serial.print(' ');
//    }
//    Serial.println();
//
//    Serial.print("IV: ");
//    for(int i=0;i<16;i++) {
//        Serial.print(aes_iv[i], HEX);
//        Serial.print(' ');
//    }
//    Serial.println();
//
//    Serial.print("Message: ");
//    for(int i=0;i<MLEN;i++) {
//        Serial.print(AESData[i], HEX);
//        Serial.print(' ');
//    }
//    Serial.println();
//
    //AESResult = AESEncrypt(AESData, AESDataLength);


//    AESCrypt(AES_DIR_ENCRYPT, aes_iv, AESData, AESResult, AESDataLength);
    //Serial.print("Encrypted: ");
    //for(uint32_t i=0;i<AESDataLength+getBlockSize();i++) {
        //Serial.print(AESResult[i], HEX);
        //Serial.print(' ');
    //}
    //Serial.println();

//    AESCrypt(AES_DIR_DECRYPT, &aesv, AESResult, AESResult2, AESDataLength);
//    Serial.print("Decrypted: ");
//    for(int i=0;i<MLEN;i++) {
//        Serial.print(AESResult2[i], HEX);
//        Serial.print(' ');
//    }
//    Serial.println();
}

uint8_t buffer[32] = {0};
uint16_t bufferPnt = 0;

void send() {
    uint32_t resLen = 0;
    Serial.print("encrypting..");
    uint8_t *res = AESEncrypt(buffer, 32, &resLen);
    Serial.println(resLen);
    header h = {ID, resLen};
    wclient.write((uint8_t *) &h, sizeof(h)); 
    wclient.write(res, (uint16_t) resLen);
    free(res);
    memset(buffer, 0x00, 32);
    bufferPnt = 0;
}

void loop() {
    while (Serial.available() > 0) {
        uint8_t val = Serial.read();
        if ((val == 8 || val == 127 || val == 27) && bufferPnt > 0) {
            bufferPnt--;
            Serial.write(val); // echo
            continue;
        }
        if (val == 26 && buffer[bufferPnt] != 0x00) {
            bufferPnt++;
            Serial.write(val); // echo
            continue;
        }
        if(val == 13) {
            send();
            Serial.println();
            continue;
        }
        Serial.write(val); // echo
        if(bufferPnt >= 32) send();
        buffer[bufferPnt] = val;
        bufferPnt++;
    }
}


