import { Controller, Tag } from "st-ethernet-ip";
import { createLog } from "../../../../logger/logger.js";
import { labelerTagRead } from "./plcTags/labelerTag.js";
import { palletSendTag } from "./plcTags/palletSendTag.js";
import { strapperFaults } from "./plcTags/strapperFault.js";

let PLC = new Controller();
let isDycoRunning = false;

// PLC address
let plcAddress = "10.44.5.4";
let isReading = false;
// Initialize the interval variable outside the function
let plcCycle: any;
let plcInterval = 500;

// Create Tag Instances
const labelerTag: any = new Tag("labeler.line_info");
const palletSend = new Tag("Zone_6.Ready_to_Send");
const strapperError = new Tag("Zone_3.Strapper_Faulted");

export const dycoConnect = async () => {
    // if we crash or start over reset the timers so we dont get duplicates
    clearInterval(plcCycle);
    if (isDycoRunning)
        return { success: false, message: "Dyco is already connected." };

    // Remove all listeners before adding a new one to prevent memory leaks
    PLC.removeAllListeners("error");

    try {
        await PLC.connect(plcAddress, 0).then(async () => {
            createLog("info", "dyco", "ocp", `We are connected to the dyco.`);
            isDycoRunning = true;

            plcCycle = setInterval(async () => {
                if (isReading) {
                    createLog(
                        "debug",
                        "dyco",
                        "ocp",
                        "Skipping cycle: previous read still in progress."
                    );
                    return;
                }
                isReading = true; // Set flag
                try {
                    await PLC.readTag(labelerTag);
                    await PLC.readTag(palletSend);
                    await PLC.readTag(strapperError);

                    // strapper check
                    strapperFaults(strapperError);

                    // send the labeler tag data over
                    labelerTagRead(labelerTag);

                    // send the end of line check over.
                    palletSendTag(palletSend);
                } catch (error: any) {
                    createLog(
                        "error",
                        "dyco",
                        "ocp",
                        `Error reading PLC tag: ${error.message}`
                    );
                } finally {
                    isReading = false; // Reset flag
                }
            }, plcInterval);
        });
    } catch (error) {
        createLog(
            "error",
            "dyco",
            "ocp",
            `There was an error in the dyco: ${error}`
        );
        await PLC.disconnect();
        isDycoRunning = false;
    }
};

export const closeDyco = async () => {
    if (!isDycoRunning)
        return { success: false, message: "Dyco is not connected." };

    console.log(`Closing the connection`);
    try {
        await PLC.disconnect();
        isDycoRunning = false;
        return {
            success: true,
            message: "Dyco Connection is now closed.",
        };
    } catch (error) {
        console.log(error);
        return {
            success: false,
            message: "There was an error closing the dyco connection.",
        };
    }
};
