const serialResultsDiv = document.getElementById("serialResults");

function progressBar(percentage, message, color){
    var readbar = document.getElementById("readBar");
    readBar.style.background = color;
    readBar.style.width = percentage +"%";
    readBar.innerHTML = message;
}

async function getServiceID(){
    var data = document.getElementById("servicetoken").innerHTML;
    return data
}

async function connectDevice() {

        //clear input
        readBar.innerHTML = '';
        serialResultsDiv.innerHTML = '';

        //set prgress bar
        progressBar("1", "", "");

    try {
        // Prompt user to select any serial port.
        const filters = [{ usbVendorId: 1027, usbProductId: 24597 }];
        port = await navigator.serial.requestPort({ filters });
        await port.open({ baudRate: 56700 });
        progressBar("10", "Connecting", "#04AA6D");

        listenToPort();

        textEncoder = new TextEncoderStream();
        writableStreamClosed = textEncoder.readable.pipeTo(port.writable);

        writer = textEncoder.writable.getWriter();
    } catch {
      if (openPort = 1){
          closePort();
          console.log("Closing port");
          alert("System is still trying to close the serial port. If this message continues to come up please refresh this page.");
        }
        else{
          alert("Your browser does not support this functionality. Please use latest Chrome or Edge browser.");
          }
      }
}

async function listenToPort() {
    const textDecoder = new TextDecoderStream();
    readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
    reader = textDecoder.readable.getReader();
    openPort = 1;

    while (true) {
        const { value, done } = await reader.read();
        if (done) {
            reader.releaseLock();
            break;
        }
        progressBar("40", "Reading", "#04AA6D");

        appendToTerminal(value);

        var item = serialResultsDiv.innerHTML;
        x = Array.from(new Set(item.split(";"))).toString();
        if (x.indexOf("SN=") > 0 && x.indexOf("HW=") > 0 && x.indexOf("FW=") >0 && x.indexOf("STATE=") > 0)
        {
          progressBar("60", "Reading device completed", "#04AA6D");
          setTimeout(getDeviceData, 4000);
          return;
        }
    }

}

async function appendToTerminal(newStuff) {
    serialResultsDiv.innerHTML += newStuff;
}


async function getDeviceData(){
  var item = serialResultsDiv.innerHTML;
  x = Array.from(new Set(item.split(";"))).toString();

  //Check if Serialnumber is retrieved from device
  if (x.indexOf("SN=") > 0){
    var a = x.indexOf("SN=");
    var b = a + 3;
    var c = b + 8;
    serial = x.substring(b,c);
    progressBar("65", "Retrieving device data", "#04AA6D");
    console.log(serial);
  
    if (x.indexOf("FW=") > 0){
      var a = x.indexOf("FW=");
      var b = a + 3;
      var c = b + 8;
      fw = x.substring(b,c);
      fw = fw.replace(/^0+/, '');
    }

    //Check if HW is retrieved from device
    if (x.indexOf("HW=") > 0 && x.indexOf("FW=") >0){
      var a = x.indexOf("HW=");
      var b = a + 3;
      var c = b + 8;
      var d = x.substring(b,c);
      var e = d.slice(-1);

      if (e.toLowerCase() !== e.toUpperCase()){
        var f = d.slice(d.length - 3)
        hw = 'R'+f;
        sw = 'R'+f;
      }
        else {
        var f = d.slice(d.length - 2)
        hw = 'R'+f;
        sw = 'R'+f;
      }

    //GET THE COMMITCODE
    commitCode = compareCommitCodes("",fw);
        
    getServiceID().then(firmwareUpdate);
    progressBar("80", "checking for available firmware", "#04AA6D");
    setTimeout(checkAvailableFirmware, 5000);
    }
    else {
      progressBar("80", "Reading of device not successful, please try again", "#ff6666");
      console.log('Reading of device not successful');
    } 
  }
}
function firmwareUpdate(data){

    var serialnumber = serial;
    var action = '/v2/products_software/sn='+serialnumber+'&version='+commitCode+'&hw_version='+hw;
    var url = link+action;
  
    var bearer = 'Bearer ' + data;
  
    fetch(url, {
            method: 'GET',
            withCredentials: true,
            credentials: 'include',
            headers: {
                'Authorization': bearer,
                'Content-Type': 'application/json'
            }
        })
        .then(response => response.json())
        .then(firmware=> {
                firmwarelocation = './firmware/'+firmware['software'];
                upgraded_version = firmware['version'];
                return firmwarelocation;
                    })
  
            .catch(error => {
             console.log(error)
            })
  
  
  }

function findShortGitCommitHash(string) {
  // Step 1: Find all hexadecimal sequences
  const hexSequencePattern = /[0-9a-f]+/gi;
  const allHexMatches = string.match(hexSequencePattern) || [];
  
  // Step 2: Filter to only include those with exactly 6 or 7 characters
  const commitHashes = allHexMatches.filter(match => match.length === 6 || match.length === 7);
  
  return commitHashes;
}
  
function compareCommitCodes(stringA, stringB) {
  // Get commit codes from both strings
  const commitCodesA = findShortGitCommitHash(stringA);
  const commitCodesB = findShortGitCommitHash(stringB);
  
  // Case 1: Check if there are matching commit codes between A and B
  for (const codeA of commitCodesA) {
    if (commitCodesB.includes(codeA)) {
      return codeA; // Return the first matching commit code
    }
  }
  
  // Case 2: If A has commit code but B doesn't
  if (commitCodesA.length > 0 && commitCodesB.length === 0) {
    return commitCodesA[0]; // Return the first commit code from A
  }
  
  // Case 3: If A has no commit code but B does
  if (commitCodesA.length === 0 && commitCodesB.length > 0) {
    return commitCodesB[0]; // Return the first commit code from B
  }
  
  // Case 4: Neither has commit code
  return "";
}

function checkAvailableFirmware(){

  if (typeof firmwarelocation !== 'undefined') {
    progressBar("90", "Validating firmware retrieved", "#04AA6D");
    hex_fw = firmwarelocation.split("/firmware/").pop();
    console.log(hex_fw)

        if (hex_fw == 'null' || hex_fw == ''){
          //document.getElementById("updateAvailabe").style.display = "none";
          progressBar("100", "No firmware found for this device", "#ff6666");
        }
        else {
          var element = document.getElementById("Device_output");
    
          //COMPARE commitCODE from DEVICE with RETURNED CODE FROM API
          if (commitCode.toUpperCase() == upgraded_version.toUpperCase()){
              readBar.innerHTML = 'Latest Firmware already on device';

              if (typeof(element) != 'undefined' && element != null)
              {
                document.getElementById("Device_output").style.display = "none";
              }
            }
            else {
              readBar.innerHTML = 'Firmware available';
              
              if (typeof(element) != 'undefined' && element != null){
                document.getElementById("Device_output").style.display = "block";
              }       
          }
        }
  }
  else{
    document.getElementById("updateAvailabe").style.display = "none";
    readBar.innerHTML = 'No firmware found for this device';
  }
  closePort();
}

async function closePort(){
        reader.cancel();
        await readableStreamClosed.catch(() => { /* Ignore the error */ });

        writer.close();
        await writableStreamClosed;

        await port.close();
        openPort = 0;
        console.log('Device connection closed');
        readBar.style.width = "100%";
}

function checkFormUpdateFirmware() {
    let buttonfirmware = document.getElementById("updateFirmware")
  
    if (document.getElementById("action_firmware").checked)
      {updateFirmware.disabled = false;
        buttonfirmware.style.display = "block";
      }
      else {
        buttonfirmware.disabled = "disabled";
        buttonfirmware.style.display = "none";
      }
  }
