/**
 * @type{String[]} tablenames
 */
let tablenames;
let socket;
let toasttimeout = 2000;

function fetchcontent(url, cb){
    fetch(url)
    .then((response)=>response.text())
    .then((data)=>cb(data))
    .catch((err)=>console.log("Error: "+err));
}

function getLoginBody(loadcomplete){
    let div = document.getElementById("appcontent")
    if (div){
         fetchcontent("login.html", (data)=>{
             div.innerHTML = data;
             loadcomplete();
         });

    }
}

function HandleLoginForm(){
    localStorage.removeItem("username");
    getLoginBody(()=>{
        let loginbutton = document.getElementById("loginbutton");
        loginbutton?.addEventListener("click",()=>{

            let username = document.getElementById("login_username")?.value;
            let password = document.getElementById("login_password")?.value;
            if (username && password){
                login(socket, username, password, (loginresult)=>{
                    if (loginresult.startsWith("welcome ")){
                        localStorage.setItem("username", username);
                        HandleFisTableForm(null);
                    }else alert("Invalid Username or Password");
                });
            } else alert("Username and Password must be filled");
        });

    });
}

/**
 * Load content of fisTable.html to div#appcontent
 * @param loadcomplete callback called when load complete
 */
function getFisTableBody(loadcomplete){
    let div = document.getElementById("appcontent")
    if (div){
         fetchcontent("fisTable.html", (data)=>{
             div.innerHTML = data;
             loadcomplete();
         });


    }
}

/**
 * Load content of fisTable.html to div#appcontent
 * @param {String|null} tablename if supplied with tablename, will getdata from server for that table
 */
function HandleFisTableForm(tablename){
    getFisTableBody(()=>{
        // clear table
        clear_fistablebody();
        // clear existing table list
        regettablenames(()=>{
            let tableexisting = document.getElementById("tableexisting");
            if (valid_date_yyyymmdd(tablename)){
                tableexisting.value = tablename;
                let getdata = document.getElementById("getdata");
                getdata.click();
            }
        });
        CreateTableEventHandler(document.getElementById("createtable"));
        DropTableEventHandler(document.getElementById("droptable"));
        GetDataEventHandler(document.getElementById("getdata"));
        InsertDataEventHandler(document.getElementById("insertdata"));
        ExportToExcelEventHandler(document.getElementById("exporttoexcel"));
        ImportFromExcelEventHandler(document.getElementById("importfromexcel"));
        LogoutEventHandler(document.getElementById("logoutbutton"));
    });

}

function geteditFlight(loadcomplete){
    let div = document.getElementById("appcontent")
    if (div){
         fetchcontent("editFlight.html", (data)=>{
             div.innerHTML = data;
             loadcomplete();
         });


    }
}

function HandleEditFlightForm(tablename, fisdata){
    if (tablename!=null && tablename.length>0){
        if (fisdata!=null){
            geteditFlight(()=>{
                let edit_AD_A = document.getElementById("edit_AD_A");
                let edit_AD_D = document.getElementById("edit_AD_D");
                if ("A"===fisdata.DA) edit_AD_A.checked = true; else edit_AD_D.checked = true;
                let edit_DI_D = document.getElementById("edit_DI_D");
                let edit_DI_I = document.getElementById("edit_DI_I");
                if ("I"===fisdata.DI) edit_DI_I.checked = true; else edit_DI_D.checked = true;
                let airlineCode = document.getElementById("edit_Alcode");
                airlineCode.value = fisdata.AirlineCode;
                let flightNumber = document.getElementById("edit_FlightNumber");
                flightNumber.value = fisdata.FlightNumber;
                let origin = document.getElementById("edit_Origin");
                origin.value = fisdata.Origin;
                let destination = document.getElementById("edit_Destination");
                destination.value = fisdata.Destination;
                let gate = document.getElementById("edit_Gate");
                gate.value = fisdata.Gate;
                let terminal = document.getElementById("edit_Terminal");
                terminal.value = fisdata.Terminal;
                let baggageClaim = document.getElementById("edit_BaggageClaim");
                baggageClaim.value = fisdata.BaggageClaim;
                if ("D"===fisdata.DA) baggageClaim.disabled = true; // departure --> disable Baggage Conveyor belt
                let checkinCounter = document.getElementById("edit_CheckIn");
                checkinCounter.value = fisdata.CheckinCounter;
                if ("A"===fisdata.DA) checkinCounter.disabled = true; // arrival --> disable check in counter
                let scheduledTime = document.getElementById("edit_scheduled");
                scheduledTime.value = DateTimeContainsT(fisdata.scheduledTime) ? fisdata.scheduledTime : ConvertToTFormat(fisdata.scheduledTime);
                let estimatedTime = document.getElementById("edit_estimated");
                estimatedTime.value = DateTimeContainsT(fisdata.estimatedTime) ? fisdata.estimatedTime : ConvertToTFormat(fisdata.estimatedTime);
                let actualTime = document.getElementById("edit_actual");
                actualTime.value = DateTimeContainsT(fisdata.actualTime) ? fisdata.actualTime : ConvertToTFormat(fisdata.actualTime);
                let gatescheduledTime = document.getElementById("edit_gateScheduled");
                gatescheduledTime.value = DateTimeContainsT(fisdata.gateScheduledTime) ? fisdata.gateScheduledTime : ConvertToTFormat(fisdata.gateScheduledTime);
                let gateestimatedTime = document.getElementById("edit_gateEstimated");
                gateestimatedTime.value = DateTimeContainsT(fisdata.gateEstimatedTime) ? fisdata.gateEstimatedTime : ConvertToTFormat(fisdata.gateEstimatedTime);
                let gateactualTime = document.getElementById("edit_gateActual");
                gateactualTime.value = DateTimeContainsT(fisdata.gateActualTime) ? fisdata.gateActualTime : ConvertToTFormat(fisdata.gateActualTime);
                let remark = document.getElementById("edit_remark");
                remark.value = fisdata.Remark;

                let cancel = document.getElementById("cancelbutton");
                if (cancelbutton){
                    cancelbutton.addEventListener("click",()=>{
                       HandleFisTableForm(tablename);
                    });
                }
                let savebutton = document.getElementById("savebutton");
                if (savebutton){
                    savebutton.addEventListener("click",()=>{
                        let need_save = false;
                        // item lain di-disabled, tidak bisa edit
                        if (gate.value!==fisdata.Gate) need_save = true;
                        if (terminal.value!==fisdata.Terminal) need_save = true;
                        if (baggageClaim.value!==fisdata.BaggageClaim) need_save = true;
                        if (checkinCounter.value!==fisdata.CheckinCounter) need_save = true;
                        if (estimatedTime.value!==fisdata.estimatedTime) need_save = true;
                        if (actualTime.value!==fisdata.actualTime) need_save = true;
                        if (gateestimatedTime.value!==fisdata.gateEstimatedTime) need_save = true;
                        if (gateactualTime.value!==fisdata.gateActualTime) need_save = true;
                        if (remark.value!==fisdata.Remark) need_save = true;
                        if (need_save){
                            fisdata.Gate = gate.value;
                            fisdata.Terminal = terminal.value;
                            fisdata.BaggageClaim = baggageClaim.value;
                            fisdata.CheckinCounter = checkinCounter.value;
                            fisdata.estimatedTime = DateTimeContainsT(estimatedTime.value) ? ConvertToSpaceFormat(estimatedTime.value) : estimatedTime.value;
                            fisdata.actualTime = DateTimeContainsT(actualTime.value) ? ConvertToSpaceFormat(actualTime.value) : actualTime.value;
                            fisdata.gateEstimatedTime = DateTimeContainsT(gateestimatedTime.value) ? ConvertToSpaceFormat(gateestimatedTime.value) : gateestimatedTime.value;
                            fisdata.gateActualTime = DateTimeContainsT(gateactualTime.value) ? ConvertToSpaceFormat(gateactualTime.value) : gateactualTime.value;

                            if (remark.value!==fisdata.Remark){
                                fisdata.Remark = remark.value;
                                // supaya AAS broadcast lagi
                                fisdata.IsRead="0";
                            }
                            fisdata.lastUpdated = DateToString(Date.now());
                            editrow(socket, tablename, fisdata.id, fisdata, (editresult)=>{
                                if ("success"===editresult){
                                    ToastMessage("Row edited successfully", toasttimeout);
                                    HandleFisTableForm(tablename);
                                } else ToastMessage("Failed to edit row, result = "+editresult, toasttimeout);
                            });

                        } else {
                            ToastMessage("No changes to save", toasttimeout);
                            HandleFisTableForm(tablename);
                        }
                    });
                }
            });
        } else ToastMessage("Select a row to edit data", toasttimeout);
    } else ToastMessage("Select a table to edit data", toasttimeout);

}

function getinputFlight(loadcomplete){
    let div = document.getElementById("appcontent")
    if (div){
         fetchcontent("inputFlight.html", (data)=>{
             div.innerHTML = data;
             loadcomplete();
         });


    }
}

/**
 * Create Input Flight Form on tablename
 * @param tablename table name to insert data
 */
function HandleInputFlightForm(tablename){
    getinputFlight(()=>{
        let radioAD_A = document.getElementById("input_AD_A");
        let radioAD_D = document.getElementById("input_AD_D");
        let radioDI_D = document.getElementById("input_DI_D");
        let radioDI_I = document.getElementById("input_DI_I");
        let airlineCode = document.getElementById("input_Alcode");
        let flightNumber = document.getElementById("input_FlightNumber");
        let origin = document.getElementById("input_Origin");
        let destination = document.getElementById("input_Destination");
        let gate = document.getElementById("input_Gate");
        let  terminal = document.getElementById("input_Terminal");
        let baggageClaim = document.getElementById("input_BaggageClaim");
        let checkinCounter = document.getElementById("input_CheckIn");
        let scheduledTime = document.getElementById("input_scheduled");
        let estimatedTime = document.getElementById("input_estimated");
        let actualTime = document.getElementById("input_actual");
        let gatescheduledTime = document.getElementById("input_gateScheduled");
        let gateestimatedTime = document.getElementById("input_gateEstimated");
        let gateactualTime = document.getElementById("input_gateActual");
        let remark = document.getElementById("input_remark");

        radioAD_A.addEventListener("change",()=>{
            if (radioAD_A.checked) {
                // arrival --> disable check in counter
                checkinCounter.disabled = true;
                if (checkinCounter.value.length>0) checkinCounter.prevvalue = checkinCounter.value;
                checkinCounter.value = "0";
                // arrival --> butuh Baggage Conveyor belt
                baggageClaim.disabled = false;
                if (baggageClaim.prevvalue) baggageClaim.value = baggageClaim.prevvalue;
            }
        });
        radioAD_D.addEventListener("change",()=>{
           if (radioAD_D.checked){
               // departure --> disable Baggage Conveyor belt
               baggageClaim.disabled = true;
               if (baggageClaim.value.length>0) baggageClaim.prevvalue = baggageClaim.value;
               baggageClaim.value = "0";
                // departure --> butuh Checkin Counter
               checkinCounter.disabled = false;
               if (checkinCounter.prevvalue) checkinCounter.value = checkinCounter.prevvalue;
           }
        });

        scheduledTime.addEventListener("change",()=>{
            if (DateTimeContainsT(scheduledTime.value)){
                // data valid
                // ketika inputflight, estimatedTime dan actualTime akan sama dengan scheduledTime
                estimatedTime.value = scheduledTime.value;
                actualTime.value = scheduledTime.value;
            } else {
                ToastMessage("Invalid Scheduled Time", toasttimeout);
            }
        });

        gatescheduledTime.addEventListener("change",()=>{
           if (DateTimeContainsT(gatescheduledTime.value)){
               // data valid
               // ketika inputflight, gateestimatedTime dan gateactualTime akan sama dengan gatescheduledTime
               gateestimatedTime.value = gatescheduledTime.value;
               gateactualTime.value = gatescheduledTime.value;
           } else{
                ToastMessage("Invalid Gate Scheduled Time", toasttimeout);
           }
        });

        let cancelbutton = document.getElementById("cancelbutton");
        cancelbutton.addEventListener("click",()=>{
            HandleFisTableForm(tablename);
        });
        let savebutton = document.getElementById("savebutton");
        savebutton.addEventListener("click",()=>{
            if (!radioAD_D.checked && !radioAD_A.checked){
                ToastMessage("Select Arrival or Departure", toasttimeout);
                return;
            }

            if (!radioDI_D.checked && !radioDI_I.checked){
                ToastMessage("Select Domestic or International", toasttimeout);
                return;
            }

            if (airlineCode.value.length!==2){
                ToastMessage("Airline Code must be 2 characters", toasttimeout);
                return;
            }

            const regex_airlinecode = /^[A-Z]{2}$/;
            if (!regex_airlinecode.test(airlineCode.value)){
                ToastMessage("Airline Code must be 2 uppercase alphabets", toasttimeout);
                return;
            }

            if (flightNumber.value.length<1 || flightNumber.value.length>4){
                ToastMessage("Flight Number must be 1 to 4 characters", toasttimeout);
                return;
            }

            const regex_flightnumber = /^[0-9]{1,4}$/;
            if (!regex_flightnumber.test(flightNumber.value)){
                ToastMessage("Flight Number must be 1 to 4 digits", toasttimeout);
                return;
            }

            if (origin.value.length!==3){
                ToastMessage("Origin must be 3 characters", toasttimeout);
                return;
            }

            const regex_origin = /^[A-Z]{3}$/;
            if (!regex_origin.test(origin.value)){
                ToastMessage("Origin must be 3 uppercase alphabets", toasttimeout);
                return;
            }

            if (destination.value.length<3){
                ToastMessage("Destination must be 3 at least characters", toasttimeout);
                return;
            }

            const regex_destination = /^([A-Z]{3})(,[A-Z]{3})*$/;
            if (!regex_destination.test(destination.value)){
                ToastMessage("Destination must be 3 uppercase alphabets. Multi Destinations must be separated by comma", toasttimeout);
                return;
            }

            let destinations = destination.value.split(",");
            if (destinations.length>1){
                destinations.forEach(dest => {
                    if (dest.trim().indexOf(origin.value)!==-1){
                        ToastMessage("Destination must be different from Origin", toasttimeout);
                        return
                    }
                })
            }

            if (gate.value.length<1){
                ToastMessage("Gate must be filled", toasttimeout);
                return;
            }

            if (terminal.value.length<1){
                ToastMessage("Terminal must be filled", toasttimeout);
                return;
            }

            if (baggageClaim.value.length<1){
                ToastMessage("Baggage Claim must be filled", toasttimeout);
                return;
            }

            if (checkinCounter.value.length<1){
                ToastMessage("Checkin Counter must be filled", toasttimeout);
                return;
            }

            if (remark.value.length<1){
                ToastMessage("Remark must be filled", toasttimeout);
                return;
            }

            if (!DateTimeContainsT(scheduledTime.value)){
                ToastMessage("Invalid Scheduled Time = "+scheduledTime.value, toasttimeout);
                return;
            }

            if (!DateTimeContainsT(estimatedTime.value)){
                ToastMessage("Invalid Estimated Time = "+estimatedTime.value, toasttimeout);
                return;
            }

            if (!DateTimeContainsT(actualTime.value)){
                ToastMessage("Invalid Actual Time = "+actualTime.value, toasttimeout);
                return;
            }

            if (!DateTimeContainsT(gatescheduledTime.value)){
                ToastMessage("Invalid Gate Scheduled Time = "+gatescheduledTime.value, toasttimeout);
                return;
            }

            if (!DateTimeContainsT(gateestimatedTime.value)){
                ToastMessage("Invalid Gate Estimated Time = "+gateestimatedTime.value, toasttimeout);
                return;
           }

            if (!DateTimeContainsT(gateactualTime.value)){
                ToastMessage("Invalid Gate Actual Time = "+gateactualTime.value, toasttimeout);
                return;
            }

            let newdata = new FisData();
            newdata.AirlineCode = airlineCode.value;
            newdata.FlightNumber = flightNumber.value;
            newdata.DA = radioAD_D.checked ? "D" : "A";
            newdata.DI = radioDI_D.checked ? "D" : "I";
            newdata.Origin = origin.value;
            newdata.Destination = destination.value;
            newdata.Gate = gate.value;
            newdata.Terminal = terminal.value;
            newdata.BaggageClaim = baggageClaim.value;
            newdata.CheckinCounter = checkinCounter.value;
            newdata.scheduledTime =  DateTimeContainsT(scheduledTime.value) ? ConvertToSpaceFormat(scheduledTime.value) : scheduledTime.value;
            newdata.estimatedTime = DateTimeContainsT(estimatedTime.value) ? ConvertToSpaceFormat(estimatedTime.value) : estimatedTime.value;
            newdata.actualTime = DateTimeContainsT(actualTime.value) ? ConvertToSpaceFormat(actualTime.value) : actualTime.value;
            newdata.gateScheduledTime = DateTimeContainsT(gatescheduledTime.value) ? ConvertToSpaceFormat(gatescheduledTime.value) : gatescheduledTime.value;
            newdata.gateEstimatedTime = DateTimeContainsT(gateestimatedTime.value) ? ConvertToSpaceFormat(gateestimatedTime.value) : gateestimatedTime.value;
            newdata.gateActualTime = DateTimeContainsT(gateactualTime.value) ? ConvertToSpaceFormat(gateactualTime.value) : gateactualTime.value;
            newdata.Remark = remark.value;
            newdata.IsRead  = "0";
            newdata.lastUpdated = DateToString(Date.now());
            insertrow(socket, tablename, newdata, (insertresult)=>{
                ToastMessage("Insert Result = "+insertresult, toasttimeout);
                // back to fisTable
                HandleFisTableForm(tablename);
            });
        });
    });
}

/**
 * Check if value is DateTime in format yyyy-MM-ddTHH:mm:ss
 * @param value value to check
 * @return {boolean} true if valid
 */
function DateTimeContainsT(value){
    if (value!=null && value.length>0){
        return /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/.test(value);
    }
    return false;
}

/**
 * Convert Date String from yyyy-MM-ddTHH:mm:ss to yyyy-MM-dd HH:mm:ss
 * @param value value to convert
 * @return {String|null} converted value
 */
function ConvertToSpaceFormat(value){
    if (value!=null && value.length>0){
        return value.replace("T"," ");
    }
    return value;
}

/**
 * Convert Date String from yyyy-MM-dd HH:mm:ss to yyyy-MM-ddTHH:mm:ss
 * @param value value to convert
 * @return {String|null} converted value
 */
function ConvertToTFormat(value){
    if (value!=null && value.length>0){
        return value.replace(" ","T");
    }
    return value;
}

/**
 * Application Start from Here !
 */
document.addEventListener("DOMContentLoaded", ()=>{


    socket = io(":7001");

    socket.on("connect",()=>{
        console.log("Connected to Server, socket id = "+socket.id);
        // Source : https://socket.io/docs/v4/connection-state-recovery
        // new on Socket.io v 4.6.0
        // if (socket.recovered){
        //     // any event missed during the disconnection period will be received now
        // } else {
        //    // new or unrecoverable session
        // }

        // get and change connection status text and button
        let textstatus = document.getElementById("text_status");
        if (textstatus) textstatus.innerHTML = "Connected";
        let btnstatus = document.getElementById("status_connection");
        if (btnstatus) btnstatus.className = "btn-connected";


    });
    socket.on("connect_error", (err)=>console.log("Connection Error: "+err));

    socket.on("disconnect",(reason,detail)=>{
        console.log("Disconnected from Server. Reason: "+reason)
        let textstatus = document.getElementById("text_status");
        if (textstatus) textstatus.innerHTML = "Disconnected";
        let btnstatus = document.getElementById("status_connection");
        if (btnstatus) btnstatus.className = "btn-disconnected";
    });


    socket.on("error", (err)=>console.log("Error: "+err));
    socket.on("message", (msg)=>console.log("Message: "+msg));
    let username = localStorage.getItem("username");
    if (username && username.length>0){
        HandleFisTableForm(null);
    } else HandleLoginForm();

})

function clear_fistablebody(){
    let fistablebody = document.getElementById("fistablebody");
    if (fistablebody) {
        fistablebody.datatag = null;
        fistablebody.innerHTML = "";
    }
}

/**
 * Get data tag identified at fistablebody
 * @return {String|null}
 */
function get_fistablebody_datatag(){
    let fistablebody = document.getElementById("fistablebody");
    if (fistablebody){
        return fistablebody.datatag;
    }
    return null;
}

/**
 * Fill table body with data
 * @param {String} tag identifier for table body as indicator
 * @param {FisData[]}data
 */
function fill_fistablebody(tag, data){
    let fistablebody = document.getElementById("fistablebody");
    if (fistablebody){
        fistablebody.datatag = tag;
        data.forEach((row)=>{
            let tr = document.createElement("tr");
            tr.appendChild(create_td_label(null, row.id));
            tr.appendChild(create_td_label(null, row.AirlineCode));
            tr.appendChild(create_td_label(null, row.FlightNumber));
            tr.appendChild(create_td_label(null, row.DA));
            tr.appendChild(create_td_label(null, row.DI));
            tr.appendChild(create_td_label(null, row.Origin));
            tr.appendChild(create_td_label(null, row.Destination));
            tr.appendChild(create_td_label(null, row.Gate));
            tr.appendChild(create_td_label(null, row.Terminal));
            tr.appendChild(create_td_label(null, row.estimatedTime));
            tr.appendChild(create_td_label(null, row.Remark));
            tr.appendChild(create_td_edit_delete_buttons(()=>{
                HandleEditFlightForm(tag, row);
            },()=>{
                if (confirm(`Are you sure to delete this row=${row.id}, Airline=${row.AirlineCode}, FlightNumber=${row.FlightNumber} ?`)){
                    deleterow(socket, tag, row.id, (deleterowresult)=>{
                        if ("success"===deleterowresult){
                            ToastMessage("Row deleted successfully", toasttimeout);
                            // reget data to refresh table
                            let btngetdata = document.getElementById("getdata");
                            if (btngetdata) btngetdata.click();
                        } else ToastMessage("Failed to delete row, result = "+deleterowresult, toasttimeout);
                    });

                }
            }));
            fistablebody.appendChild(tr);
        });
    }
}

/**
 * Create td element contains label inside
 * @param id not null, set the id of label
 * @param value value of label
 * @return {HTMLTableCellElement} created td element
 */
function create_td_label(id, value){
    const td = document.createElement("td");
    const lbl = document.createElement("label");
    lbl.innerHTML = value;
    if (id!=null && id.length>0) lbl.id = id;
    td.appendChild(lbl);
    return td;
}

/**
 * Create td element contains edit and delete buttons
 * @param {Function} cbedit callback called when edit button clicked
 * @param {Function} cbdelete callback called when delete button clicked
 * @return {HTMLTableCellElement} created td element
 */
function create_td_edit_delete_buttons(cbedit, cbdelete){
    const td = document.createElement("td");
    const div1 = document.createElement("div");
    div1.className = "row";

    const div2a = document.createElement("div");
    div2a.className = "col";
    const btn1 = document.createElement("button");
    btn1.className = "btn btn-sm btn-primary";
    btn1.addEventListener("click", cbedit);
    const span1 = document.createElement("span");
    span1.className = "fa-solid fa-pencil";
    btn1.appendChild(span1);
    div2a.appendChild(btn1);

    const div2b = document.createElement("div");
    div2b.className = "col";
    const btn2 = document.createElement("button");
    btn2.className = "btn btn-sm btn-danger";
    btn2.addEventListener("click", cbdelete);
    const span2 = document.createElement("span");
    span2.className = "fa-solid fa fa-trash";
    btn2.appendChild(span2);
    div2b.appendChild(btn2);


    div1.appendChild(div2a);
    div1.appendChild(div2b);

    td.appendChild(div1);
    return td;
}

/**
 * To get table names from server
 * @param {Function} finishcallback callback called when finish
 */
function regettablenames(finishcallback){
    let tableexisting = document.getElementById("tableexisting");
    tableexisting.options.length = 0;
    tablenames = [];

    socket.emit("gettablenames", (reply)=>{
        if (reply!=null){
            if ("success"===reply.result){
                if (Array.isArray(reply.data) && reply.data.length>0){
                    tablenames = reply.data.map(tn => ConvertDateFormat1(tn));
                    let tableexisting = document.getElementById("tableexisting");
                    tablenames.forEach(tablename => {
                        let option = document.createElement("option");
                        option.text = tablename;
                        tableexisting.add(option);
                    });
                    tableexisting.selectedIndex = -1;

                    if (finishcallback) finishcallback();
                    return;
                } else ToastMessage("gettablename result is not array or empty", toasttimeout);
            }  else ToastMessage("Failed to get table names", toasttimeout);
        } else ToastMessage("No reply from gettablenames",toasttimeout);
        if (finishcallback) finishcallback();
    });
}

/**
 * To handle button click for Create Table
 * @param {HTMLElement} btn Button for Create Table
 */
function CreateTableEventHandler(btn){
    btn?.addEventListener("click",()=>{
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        // textarea untuk input tablename di sini , dalam format yyyy-MM-dd
        let tablename = document.getElementById("tablename");

        if (valid_date_yyyymmdd(tablename?.value)){
            if (tablenames.includes(tablename.value)){
                ToastMessage("Table already exists", toasttimeout);
                return;
            }
            createtable(socket, tablename.value, (createresult)=>{
                if ("success"===createresult){
                    regettablenames(null);
                    ToastMessage("Table created successfully", toasttimeout);
                } else ToastMessage("Failed to create table, result = "+createresult, toasttimeout);
            });

        } else ToastMessage("Valid tablename in format YYYY-MM-DD, from year 1970 to 2100", toasttimeout);
    })
}

/**
 * To handle button click for Drop Table
 * @param {HTMLElement} btn Button untuk Drop Table 
 */
function DropTableEventHandler(btn){
    btn?.addEventListener("click",()=>{
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        // textarea untuk input tablename di sini , dalam format yyyy-MM-dd
        let tableexisting = document.getElementById("tableexisting");

        if (tableexisting.options.length>0){
            if (valid_date_yyyymmdd(tableexisting?.value)){
                let tablename = tableexisting.value;
                if (confirm("Are you sure to drop table "+tablename+" ?")){
                    droptable(socket, tablename, (dropresult)=>{
                        if ("success"===dropresult){
                            if (tablename===get_fistablebody_datatag()){
                                // table yang di drop adalah table yang sedang ditampilkan
                                clear_fistablebody();
                            }
                            regettablenames(null);
                            ToastMessage("Table dropped successfully", toasttimeout);
                        } else ToastMessage("Failed to drop table, result = "+dropresult, toasttimeout);
                    });
                } else ToastMessage("Drop table cancelled",toasttimeout);
            } else ToastMessage("Valid tablename in format YYYY-MM-DD, from year 1970 to 2100", toasttimeout);
        } else ToastMessage("No table to drop", toasttimeout);

    })
}

/**
 * To handle button click for Get Data
 * @param {HTMLElement} btn Button untuk Get Data 
 */
function GetDataEventHandler(btn){
    btn?.addEventListener("click",()=>{
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        // textarea untuk input tablename di sini , dalam format yyyy-MM-dd
        let tableexisting = document.getElementById("tableexisting");

        if (valid_date_yyyymmdd(tableexisting?.value)){
            let filter_airline = document.getElementById("filter_airline")?.value;
            let filter_flightnumber = document.getElementById("filter_flightnumber")?.value;
            let filter_da = document.getElementById("filter_da")?.value;
            let filter_di = document.getElementById("filter_di")?.value;
            getdata(socket, tableexisting.value,filter_airline,filter_flightnumber,filter_da,filter_di, (getdataresult)=>{
                if (["success","no data"].includes(getdataresult.result)){
                    let tabletitle = document.getElementById("tabletitle");
                    tabletitle.innerHTML = "Flight Schedule For  "+tableexisting.value;
                    clear_fistablebody()
                    fill_fistablebody(tableexisting.value, getdataresult.data);
                } else ToastMessage("Failed to get data, result = "+getdataresult.result, toasttimeout);
            });

        } else ToastMessage("Valid tablename in format YYYY-MM-DD, from year 1970 to 2100",toasttimeout);
    })
}


function ExportToExcelEventHandler(btn){
    btn?.addEventListener("click",()=>{
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        let tablename = fistablebody?.datatag;
        if (valid_date_yyyymmdd(tablename)){
            exporttoxls(socket, tablename, (exportresult)=>{
                if ("success"===exportresult.result){
                    if (exportresult.size>0){
                        if (exportresult.filename.length>0){

                            fetch(exportresult.filename)
                                .then(response => {
                                    if (response.ok)
                                        return response.blob();
                                    else ToastMessage("Failed to fetch file "+exportresult.filename, toasttimeout);
                                })
                                .then(blob => {
                                    const url = window.URL.createObjectURL(blob);
                                    const a = document.createElement('a');
                                    a.style.display = 'none';
                                    a.href = url;
                                    a.download = "export.xlsx";
                                    document.body.appendChild(a);
                                    a.click();
                                    window.URL.revokeObjectURL(url);
                                })
                                .catch(error => {
                                    console.error(error);
                                    ToastMessage("Failed to fetch file "+exportresult.filename, toasttimeout);
                                })

                        } else ToastMessage("No filename to export", toasttimeout);
                    } else ToastMessage("No data to export", toasttimeout);
                } else ToastMessage("Failed to export data, result = "+exportresult.result, toasttimeout);
            });


        } else ToastMessage("Select a table to export to Excel", toasttimeout);
    })
}

function ImportFromExcelEventHandler(btn){
    btn?.addEventListener("click",()=>{
        console.log("Import from Excel button clicked");
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        let tablename = fistablebody?.datatag;
        if (valid_date_yyyymmdd(tablename)){
            let filename = document.getElementById("filename");
            if (filename!=null && filename.value.length>0){
                if (confirm("Are you sure to import data from "+filename.value+" to "+tablename+" ? Existing data will be replaced")){
                    // importfromxls(socket, tablename, filename.valu, filename.files[0], (importresult)=>{
                    //     console.log("importresult = "+importresult);
                    //     if ("success"===importresult){
                    //         ToastMessage("Data imported successfully", toasttimeout);
                    //         // reget data to refresh table
                    //         let btngetdata = document.getElementById("getdata");
                    //         if (btngetdata) btngetdata.click();
                    //     } else ToastMessage("Failed to import data, result = "+importresult, toasttimeout);
                    // });

                    let formdata = new FormData();
                    formdata.append("file", filename.files[0]);
                    formdata.append("tablename", tablename);
                    fetch("/import",{
                        method: "POST",
                        body: formdata
                    })
                        .then(response => response.json())
                        .then(data => {
                            console.log(JSON.stringify(data));

                            if (data.result==="success"){
                                ToastMessage("Data imported successfully", toasttimeout);
                                let btngetdata = document.getElementById("getdata");
                                if (btngetdata) btngetdata.click();

                            } else ToastMessage("Failed to import data, result = " + data.result, toasttimeout);

                        })
                        .catch(error => {
                            console.error("Error: "+error);
                            ToastMessage("Failed to import data, error = "+error, toasttimeout);
                        })
                } else ToastMessage("Import data cancelled", toasttimeout);
            } else ToastMessage("Select a file to import", toasttimeout);
        } else ToastMessage("Choose a table to import from Excel", toasttimeout);
    })
}

function LogoutEventHandler(btn){
    btn?.addEventListener("click",()=>{
        if(confirm("Are you sure to logout ?")) {
            localStorage.removeItem("username");
            HandleLoginForm();
        }
    })
}


/**
 * To handle button click for Insert Data
 * @param {HTMLElement} btn Button to insert data
 */
function InsertDataEventHandler(btn){
    btn?.addEventListener("click",()=>{
        // table untuk display FisData di sini
        let fistablebody = document.getElementById("fistablebody");
        let tablename = fistablebody?.datatag;
        if (valid_date_yyyymmdd(tablename)){
            HandleInputFlightForm(tablename);
        } else ToastMessage("Select a table to insert data",toasttimeout);
    })
}

/**
 * Convert value in format yyyyMMdd to yyyy-MM-dd
 * @param {String} value value to convert
 * @returns {String} converted value
 */
function ConvertDateFormat1(value){
       if (validstring(value) && value.length===8){
              let year = value.substring(0,4);
              let month = value.substring(4,6);
              let day = value.substring(6,8);
              if (valid_day_month_year(+day,+month,+year)){
                    return year+"-"+month+"-"+day;
              }
       }
       // kalau beda format, return as is
         return value;
}

/**
 * Check if given day, month, year is valid
 * @param {number} day
 * @param {number} month
 * @param {number} year
 * @return {boolean} true if valid
 */
function valid_day_month_year(day,month,year){
    if (day>0 && day<32){
        if (month>0 && month<13){
            if (year>=1970 && year<=2100){
                const DaysInMonth = new Date(year, month, day).getDate();
                return (day <= DaysInMonth);
            }
        }
    }
    return false;
}

/**
 * Convert Date to String in format yyyy-MM-dd
 * @param timestamp
 * @returns {string}
 */
function DateToString(timestamp){
    const date = new Date(timestamp);

    // Get the individual components of the date
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-based
    const day = String(date.getDate()).padStart(2, '0');
    const hours = String(date.getHours()).padStart(2, '0');
    const minutes = String(date.getMinutes()).padStart(2, '0');
    const seconds = String(date.getSeconds()).padStart(2, '0');

    // Format the date string
    return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}

const regex_tablename =  /^\d{4}-\d{2}-\d{2}$/

/**
 * Check if a value is valid date in format yyyy-MM-dd
 * @param {String} value 
 * @returns true if format valid
 */
function valid_date_yyyymmdd(value){
    if (validstring(value)){
        if (regex_tablename.test(value)){
            const [year, month, day] = value.split("-").map(Number);
            return valid_day_month_year(day,month,year);
        }
    }
    return false;
}

/**
 * check if a value is valid string and actually have content
 * @param {String} value 
 * @returns true if valid
 */
function validstring(value){
    if (value!=null){
        if (value.length>0){
            return true;
        }
    }
    return false;
}





/**
 * Show ToastMessage
 * @param {String} message message to display
 * @param {number} timeout timeout in ms
 */
function ToastMessage(message, timeout){
    let snackbar = document.getElementById("snackbar");

    if (snackbar==null) return;
    if (timeout<1) return;
    if (message!=null && message.length>0){
        snackbar.innerHTML = message;
        snackbar.className = "show";
        setTimeout(function(){ snackbar.className = snackbar.className.replace("show", ""); }, timeout);
    }
}


