'use strict';

goog.provide('Blockly.Python.bluetooth');

goog.require('Blockly.Python');

Blockly.Python['bluetooth_setup'] = function(block) {
    let baudNum = block.getFieldValue('BAUD');
    Blockly.Python.addSetup('bluetooth_serial_begin', 'Serial1.begin(' + baudNum + ');', false);

    let receivedDo = Blockly.Python.statementToCode(block, 'RECEIVED_DO');
    let option = block.getFieldValue('OPTIONS');
    var cmdvar = Blockly.Python.variableDB_.getName(
        block.getFieldValue('CMDVAR'), Blockly.Variables.NAME_TYPE);
    let code = "";

    if (option === "string") {
        code = "while (Serial1.available()) {\n" +
            "  delay(10);\n" +
            "  char c = Serial1.read();\n" +
            "  " + cmdvar + " += c;\n" +
            "}\n" + receivedDo +
            "\n" + cmdvar + " = \"\";\n";
    } else if (option === "number") {
        code = "if (Serial1.available() > 0) {\n" +
            "  " + cmdvar + " = Serial1.read();\n" +
            "}\n" + receivedDo;
    } else if (option === "array") {
        var length = block.getFieldValue("LENGTH");
        var argument0 = '{';
        for (var i = 0; i < length - 1; i++) argument0 += '0,';
        argument0 += "0}"
        var decl = 'int ' + cmdvar + '[' + length + '] = ' + argument0 + ';\n';
        Blockly.Python.addDeclaration('bluetooth_list', decl);
        code = "int n = " + 'sizeof(' + cmdvar + ')/sizeof(' + cmdvar + '[0]);\n' +
            "while (Serial1.available() < n) { }\n" +
            "for (int b_n = 0; b_n < n; b_n++) {\n" +
            "  " + cmdvar + "[b_n] = Serial1.read();\n" +
            "}\n" + receivedDo;
    }
    return code;
};

Blockly.Python['bluetooth_text_getCommand'] = function(block) {
    var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
        Blockly.Variables.NAME_TYPE);
    return [code, Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['bluetooth_number_getCommand'] = function(block) {
    var code = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
        Blockly.Variables.NAME_TYPE);
    return [code, Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['bluetooth_list_getCommand'] = function(block) {
    var variab = Blockly.Python.variableDB_.getName(block.getFieldValue('VAR'),
        Blockly.Variables.NAME_TYPE);
    var index = block.getFieldValue("INDEX");
    var code = variab + '[' + index + ']';
    return [code, Blockly.Python.ORDER_ATOMIC];
};

Blockly.Python['bluetooth_intercomms_send'] = function(block) {
    var baud = block.getFieldValue("BAUD");
    Blockly.Python.addDeclaration("BT_Serial_sendState", "int BTserialSendState = 0;");
    Blockly.Python.addSetup('serial1', "Serial1.begin(" + baud + ");");

    var BT_Serial_SendData = 'void BTserialSendData() {\n' +
        '   int BTserialDataLength = BTserialDataPackage().length() + 1;\n' +
        '   char BTserialDataBuf[BTserialDataLength];\n' +
        '   BTserialDataPackage().toCharArray(BTserialDataBuf, BTserialDataLength);\n' +
        '    if ( BTserialSendState == 0 ) {\n' +
        '        Serial1.write(BTserialDataBuf);\n' +
        '    }\n' +
        '    if ( (millis() / 100) % 4 == 3 && BTserialSendState == 0) {\n' +
        // Send data set to WiFi Module.\n'
        '        Serial1.write(BTserialDataBuf);\n' +
        '        BTserialSendState = 1;\n' +
        '    } else if ( (millis() / 100) % 4 == 1) {\n' +
        '        BTserialSendState = 0;\n' +
        '    }\n' +
        '}\n';
    Blockly.Python.addFunction("BTSerialSendData", BT_Serial_SendData);


    var item_value = ''
    var BTserial_DataPackage = 'String BTserialDataPackage() { \n' +
        '  String data = "";\n' +
        '  data += "SOF";\n' // Set up a "SOF" initializer for data validation usage.
    for (var n = 0; n < this.itemCount_; n++) {
        item_value = Blockly.Python.valueToCode(this, 'ADD' + n,
            Blockly.Python.ORDER_NONE) || '0';
        BTserial_DataPackage += '  data += "|";\n  data += ' + item_value + ';\n'
    }
    BTserial_DataPackage += '  data += "|";\n  data += "\\r\\n";\n  ' +
        '  return data;\n}\n';
    Blockly.Python.addFunction("BTSerialDataPackage", BTserial_DataPackage);
    var code = "";
    code += "BTserialSendData();\n";
    return code;
};

Blockly.Python['bluetooth_intercomms_receive'] = function(block) {
    var baud = block.getFieldValue("BAUD");
    var timeout = block.getFieldValue("TIMEOUT");
    Blockly.Python.addSetup('serial1_trans', "Serial1.begin(" + baud + ");\n  Serial1.setTimeout(" + timeout + ");");
    Blockly.Python.addDeclaration("BTserialDataReceived", 'String BTserialDataReceived;\n');

    var BTserial_DataFilter = 'int BTserialDataFilter() {\n' +
        '  if (Serial1.available() > 0) {\n' +
        '    BTserialDataReceived = Serial1.readStringUntil("\\r\\n");\n' +
        '  }\n' +
        '  if (BTgetSerialDataValue(BTserialDataReceived, \'|\', 0) == "SOF") {\n' +
        '    return 1;\n' +
        '  } else {\n' +
        '    return 0;\n' +
        '  }\n' +
        '}\n'
    Blockly.Python.addFunction("BTserialDataFilter", BTserial_DataFilter);

    var BTserial_getDataValue = 'String BTgetSerialDataValue(String data, char separator, int index)\n' +
        '{\n' +
        '  int found = 0;\n' +
        '  int strIndex[] = {0, -1};\n' +
        '  int maxIndex = data.length() - 1;\n' +
        '  for (int i = 0; i <= maxIndex && found <= index; i++) {\n' +
        '    if (data.charAt(i) == separator || i == maxIndex) {\n' +
        '      found++;\n' +
        '      strIndex[0] = strIndex[1] + 1;\n' +
        '      strIndex[1] = (i == maxIndex) ? i + 1 : i;\n' +
        '    }\n' +
        '  }\n' +
        '  return found > index ? data.substring(strIndex[0], strIndex[1]) : "";\n' +
        '}\n'
    Blockly.Python.addFunction("BTgetSerialDataValue", BTserial_getDataValue);


    var code = 'boolean BTserialReceiveCheck_ = BTserialDataFilter();\n' +
        'if (!BTserialReceiveCheck_) {\n' +
        '   Serial.println("Error receiving data from Bluetooth Module.");\n' +
        '   return;\n' +
        ' }\n'
    return code;
};

Blockly.Python['bluetooth_intercomms_receive_getData'] = function(block) {
    var index = parseInt(block.getFieldValue("INDEX")) + 1;
    var type = block.getFieldValue("TYPE")
    var code = "BTgetSerialDataValue(BTserialDataReceived, '|', " + index + ")" + type;
    return [code, Blockly.Python.ORDER_ATOMIC];
};


/******************************** */

Blockly.Python['bluetooth_intercomms_send_old'] = function(block) {
    var checkbit = "#define SOP '<'\n" +
        "#define EOP '>'\n";
    Blockly.Python.addDeclaration("wifi_dataTransfer_checkbit", checkbit);
    var baud = block.getFieldValue("BAUD")
    Blockly.Python.addSetup('mainwifi_setup', "Serial1.begin(" + baud + ");");

    // var datavar = Blockly.Python.variableDB_.getName(
    // block.getFieldValue('dataVar'), Blockly.Variables.NAME_TYPE);
    var length = block.itemCount_;
    var dataLength = length + "+2";
    var code = "unsigned char DataOut_[" + dataLength + "];\n" +
        "DataOut_[0] = SOP;\n"
    for (let i = 1; i < length + 1; i++) {
        var data_item = Blockly.Python.valueToCode(block, "ADD" + (i - 1), Blockly.Python.ORDER_ATOMIC) || 0;
        code += "DataOut_[" + i + "] = " + data_item + ";\n"
    }
    code += "DataOut_[" + length + "+1] = EOP;\n" +
        "Serial1.write(DataOut_, " + dataLength + ");\n" +
        "delay(50);\n";
    return code;
};

Blockly.Python['bluetooth_intercomms_receive_old'] = function(block) {
    var checkbit = "#define SOP '<'\n" +
        "#define EOP '>'\n";
    Blockly.Python.addDeclaration("wifi_dataTransfer_checkbit", checkbit);
    var length = block.getFieldValue("LENGTH");
    var baud = block.getFieldValue("BAUD")
    Blockly.Python.addSetup('mainwifi_setup', "Serial1.begin(" + baud + ");");
    var MsgReceiveStatus = "bool started = false;\n" +
        "bool ended = false;\n" +
        "int index_i;\n";
    Blockly.Python.addDeclaration("wifi_dataTransfer_MsgReceiveStatus", MsgReceiveStatus);
    Blockly.Python.addDeclaration("BT_interCommms_receive", "int BTIC_receive[" + length + "] = {0};");
    var datavar = "BTIC_receive"
    var dataIn_function = "int handleDataIn() {\n" +
        "  while (Serial1.available() > 0) {\n" +
        "    int inChar = Serial1.read();\n" +
        "    if(inChar == SOP) {\n" +
        "      index_i = 0;\n" +
        "      started = true;\n" +
        "      ended = false;\n" +
        "    } else if(inChar == EOP) {\n" +
        "      ended = true;\n" +
        "      break;\n" +
        "    }else if((index_i < " + length + ")&&started&&(!ended)) {\n" +
        "      " + datavar + "[index_i] = inChar;\n" +
        "      index_i++;\n" +
        "    }\n" +
        "  }\n" +
        "  if(started && ended) {\n" +
        "    return 1;\n" +
        "  } else {\n" +
        "    return 0;\n" +
        "  }\n" +
        "}\n";
    Blockly.Python.addFunction("mainwifi_dataIn_function", dataIn_function);
    var code = "boolean receiveMsgsuccess_ = handleDataIn();\n";
    return code;
};

Blockly.Python['bluetooth_intercomms_receive_getData_old'] = function(block) {
    var index = block.getFieldValue("INDEX");
    var code = "BTIC_receive[" + index + "]";
    return [code, Blockly.Python.ORDER_ATOMIC];
};

/******************************** */

Blockly.Python['bluetooth_at_slave'] = function(block) {
    var baud = block.getFieldValue("BAUD")
    var BT_at_slave_decl = 'int bluetoothATModeserialSendState = 0;\n' +
        'char c = \' \';\n';
    Blockly.Python.addDeclaration("BT_at_slave_decl", BT_at_slave_decl);
    var BT_at_slave_setup = '  Serial.begin(' + baud + ');\n' +
        '  Serial1.begin(38400);\n'
    Blockly.Python.addSetup("BT_at_slave_setup", BT_at_slave_setup);
    var BT_at_slave_func = 'void bluetoothATModeInteractive() {\n' +
        '  while (Serial1.available() > 0) {\n' +
        '    c = Serial1.read();\n' +
        '    Serial.write(c);\n' +
        '  }\n' +
        '  while (Serial.available() > 0) {\n' +
        '    c = Serial.read();\n' +
        '    Serial1.write(c);\n' +
        '  }\n' +
        '}\n'
    Blockly.Python.addFunction("BT_at_slave_func", BT_at_slave_func);
    var code = '  bluetoothATModeInteractive();\n' +
        '  // Slave\n' +
        '  if ( (millis() / 1000) % 50 == 5 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("  ____    _                  _                     _     _     ");\n' +
        '    Serial.println(" | __ )  | |  _   _    ___  | |_    ___     ___   | |_  | |__  ");\n' +
        '    Serial.println(" |  _ \\  | | | | | |  / _ \\ | __|  / _ \\   / _ \\  | __| | \'_ \\ ");\n' +
        '    Serial.println(" | |_) | | | | |_| | |  __/ | |_  | (_) | | (_) | | |_  | | | |");\n' +
        '    Serial.println(" |____/  |_|  \\__,_|  \\___|  \\__|  \\___/   \\___/   \\__| |_| |_|");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("  ____    _                        ");\n' +
        '    Serial.println(" / ___|  | |   __ _  __   __   ___ ");\n' +
        '    Serial.println(" \\___ \\  | |  / _` | \\ \\ / /  / _ ");\n' +
        '    Serial.println("  ___) | | | | (_| |  \\ V /  |  __/");\n' +
        '    Serial.println(" |____/  |_|  \\__,_|   \\_/    \\___|");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("1. Testing communication:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 6) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 7 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("2. Reset previous configuration:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+ORGL\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 8) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 10 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("3. Set up UART configuration: AT+UART=' + baud + ',0,0");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+UART=' + baud + ',0,0\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 11) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 13 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("4. Set up pairing mode, prevent outside connection: AT+CMODE=0");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+CMODE=0\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 14) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 16 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("5. Set up pairing mode, set as Slave Mode: AT+ROLE=0");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+ROLE=0\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 17) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 18 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("6. Getting MAC address:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+ADDR\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 19) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 21 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("7. Done, reset bluetooth module to normal state.");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+RESET\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 22) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n'

    return code;
}

Blockly.Python['bluetooth_at_master'] = function(block) {
    var baud = block.getFieldValue("BAUD");
    var addr = block.getFieldValue("ADDR").replace(/:/g, ",");
    var BT_at_master_decl = 'int bluetoothATModeserialSendState = 0;\n' +
        'char c = \' \';\n'
    Blockly.Python.addDeclaration("BT_at_master_decl", BT_at_master_decl);
    var BT_at_master_setup = '  Serial.begin(' + baud + ');\n' +
        '  Serial1.begin(38400);\n';
    Blockly.Python.addSetup("BT_at_master_setup", BT_at_master_setup);
    var BT_at_master_fun = 'void bluetoothATModeInteractive() {\n' +
        '  while (Serial1.available() > 0) {\n' +
        '    c = Serial1.read();\n' +
        '    Serial.write(c);\n' +
        '  }\n' +
        '  while (Serial.available() > 0) {\n' +
        '    c = Serial.read();\n' +
        '    Serial1.write(c);\n' +
        '  }\n' +
        '}\n';
    Blockly.Python.addFunction("BT_at_master_fun", BT_at_master_fun)
    var code = '  bluetoothATModeInteractive();\n' +
        '  // Master\n' +
        '  if ( (millis() / 1000) % 50 == 5 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("  ____    _                  _                     _     _     ");\n' +
        '    Serial.println(" | __ )  | |  _   _    ___  | |_    ___     ___   | |_  | |__  ");\n' +
        '    Serial.println(" |  _ \\  | | | | | |  / _ \\ | __|  / _ \\   / _ \\  | __| | \'_ \\ ");\n' +
        '    Serial.println(" | |_) | | | | |_| | |  __/ | |_  | (_) | | (_) | | |_  | | | |");\n' +
        '    Serial.println(" |____/  |_|  \\__,_|  \\___|  \\__|  \\___/   \\___/   \\__| |_| |_|");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("  __  __                 _                 ");\n' +
        '    Serial.println(" |  \\/  |   __ _   ___  | |_    ___   _ __ ");\n' +
        '    Serial.println(" | |\\/| |  / _` | / __| | __|  / _ \\ | \'__|");\n' +
        '    Serial.println(" | |  | | | (_| | \\__ \\ | |_  |  __/ | |   ");\n' +
        '    Serial.println(" |_|  |_|  \\__,_| |___/  \\__|  \\___| |_|   ");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("");\n' +
        '    Serial.println("1. Testing communication:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 6) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 7 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("2. Reset previous configuration:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+ORGL\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 8) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 10 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("3. Set up UART configuration: AT+UART=' + baud + ',0,0");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+UART=' + baud + ',0,0\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 11) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 13 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("4. Set up pairing mode, prevent outside connection: AT+CMODE=0");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+CMODE=0\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 14) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 16 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("5. Set up pairing mode, set as Master Mode: AT+ROLE=1");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+ROLE=1\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 17) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 18 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("6. Binding slave device:");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+BIND=' + addr + '\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 19) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n' +
        '  if ( (millis() / 1000) % 50 == 21 && bluetoothATModeserialSendState == 0) {\n' +
        '    Serial.println("");\n' +
        '    Serial.println("7. Done, reset bluetooth module to normal state.");\n' +
        '    Serial.print("- ");\n' +
        '    Serial1.write("AT+RESET\\r\\n");\n' +
        '    bluetoothATModeserialSendState = 1;\n' +
        '  } else if ( (millis() / 1000) % 50 == 22) {\n' +
        '    bluetoothATModeserialSendState = 0;\n' +
        '  }\n'

    return code;
}

Blockly.Python['bluetooth_at_interaction'] = function(block) {
    var dropdown_name = block.getFieldValue('bluetooth_at_interaction_baud');

    Blockly.Python.addDeclaration('bluetooth_at_interaction_declare', 'char c = \' \';\n');

    Blockly.Python.addSetup('bluetooth_at_interaction_setup', '' +
        'Serial.begin(' + dropdown_name + ');\n' +
        'Serial1.begin(' + dropdown_name + ');\n' +
        '');

    Blockly.Python.addFunction('bluetooth_at_interaction_function', '' +
        'void _bluetoothATmode() {\n' +
        '  if (Serial1.available())\n' +
        '    Serial.write(Serial1.read());\n' +
        '  if (Serial.available())\n' +
        '    Serial1.write(Serial.read());\n' +
        '}\n' +
        '');

    var code = '_bluetoothATmode();\n';
    return code;
};