dofile("common.inc");
dofile("fishing_func.inc");
dofile("settings.inc");

----------------------------------------
--          Global Variables          --
----------------------------------------
CurrentLure = ""; -- Don't Edit
gui_log_fish = {}; -- Don't Edit, holds log display
gui_log_fish2 = {}; -- Don't Edit, holds log display
lostlure_log = {}; -- Don't Edit, holds log display
CurrentLureIndex = 1; -- 1 = First Lure Player Owns in alphabetical order
QCurrentLureIndex = 1;
PlayersLures = {}; -- Don't Edit, Holds Current Player Lures

windowRight = lsGetWindowSize()[0];
windowBottom = lsGetWindowSize()[1];

castcount = 0;
GrandTotalCaught = 0;
GrandTotalCasts = 0;
GrandTotaldb = 0;
GrandTotalStrange = 0;
GrandTotalOdd = 0;
GrandTotalUnusual = 0;
GrandTotalLuresUsed = 0;
GrandTotalLostLures = 0;
GrandTotalFailed = 0;
lastLostLure = "";
LostLure = 0;
LureType = "";
lastLostLureType = "";
skipLure = false;
lastCastWait = 0;
castWait = 0;

SNum = 0;
Sfish = "";
muteSoundEffects = false;
TotalCasts = 5;
SkipCommon = false; -- Skips to next lure if fish caught is a common (Choose True or False).
displayCommon = false; -- Does not display common fish in the last 10 caught list
LogFails = false; -- Do you want to add Failed Catches to log file? 'Failed to catch anything' or 'No fish bit'.
AutoFillet = true; -- Do you want to auto-fillet fish if menu is pinned?
----------------------------------------

function setOptions()
    local is_done = false;
    local count = 1;
    local z = 0;

    while not is_done do
        lsDoFrame();
        checkBreak();
        local y = 10;

        lsPrint(10, y, 0, 0.7, 0.7, 0xffffffff, "# Casts until lure switches:");
        TotalCasts = readSetting("TotalCasts", TotalCasts);
        is_done, TotalCasts = lsEditBox("totalcasts", 185, y, 0, 40, 0, 0.8, 0.8, 0x000000ff, TotalCasts);
        TotalCasts = tonumber(TotalCasts);
        if not TotalCasts then
            is_done = false;
            lsPrint(160, y, 10, 0.7, 0.7, 0xFF2020ff, "MUST BE A NUMBER");
        end
        writeSetting("TotalCasts", TotalCasts);
        y = y + 15;
        lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.7, 0.7, 0xffff40ff,
            "---------------------------------------------------------------");
        y = y + 15;
        lsPrint(10, y + 1, 0, 0.6, 0.6, 0xc0c0ffff, "Main chat MUST be wide enough so no lines wrap!");
        y = y + 15;
        lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.7, 0.7, 0xffff40ff,
            "---------------------------------------------------------------");
        y = y + 20;

        lsSetCamera(0,0,lsScreenX*1.4,lsScreenY*1.4);
        lsScrollAreaBegin("optionsScroll", 10, y+30, 5, (windowRight*1.4)-20, (windowBottom*1.4)-315);

        muteSoundEffects = readSetting("muteSoundEffects", muteSoundEffects);
        muteSoundEffects = lsCheckBox(15, y-70, 10, 0xffffffff, " Mute Sound Effects", muteSoundEffects);
        writeSetting("muteSoundEffects", muteSoundEffects);
        y = y + 20;

        SkipCommon = readSetting("SkipCommon", SkipCommon);
        SkipCommon = lsCheckBox(15, y-65, 10, 0xFFFFFFff, " Skip Common Fish", SkipCommon);
        writeSetting("SkipCommon", SkipCommon);
        y = y + 20;

        AutoFillet = readSetting("AutoFillet", AutoFillet);
        AutoFillet = lsCheckBox(15, y-60, 10, 0xFFFFFFff, " Automatically Fillet Fish", AutoFillet);
        writeSetting("AutoFillet", AutoFillet);
        y = y + 20;

        if not SkipCommon then
            displayCommon = readSetting("displayCommon", displayCommon);
            displayCommon = lsCheckBox(15, y-35, 10, 0xFFFFFFff, " Display Common Fish Caught", displayCommon);
            writeSetting("displayCommon", displayCommon);
            y = y + 20;
        end

        writeStats = readSetting("writeStats", writeStats);
        writeStats = lsCheckBox(15, y-30, 10, 0xFFFFFFff, " Write Fishing Statistics", writeStats);
        writeSetting("writeStats", writeStats);
        y = y + 20;

        LogFails = readSetting("LogFails", LogFails);
        LogFails = lsCheckBox(15, y-25, 10, 0xFFFFFFff, " Log Failed Catches (Log Everything)", LogFails);
        writeSetting("LogFails", LogFails);

        lsScrollAreaEnd(y);
        lsSetCamera(0,0,lsScreenX*1.0,lsScreenY*1.0);

        if SkipCommon then
            lsPrintWrapped(15, y+70, z, lsScreenX, 0.6, 0.6, 0xffff80ff,
                "If a Common Fish is caught, then switch to next lure.\n" ..
                    "(Abdju, Chromis, Catfish, Carp, Oxyrynchus, Perch, Phagrus, Tilapia)");
        end

        if setResume then
            buttonName = "Set/Resume";
        else
            buttonName = "Start";
        end
        if TotalCasts ~= nil then
            if lsButtonText(10, lsScreenY - 30, 0, 100, 0x00ff00ff, buttonName) then
                is_done = 1;
                setResume = false;
            end
        end
        if lsButtonText(lsScreenX - 110, lsScreenY - 30, 0, 100, 0xFF0000ff, "End script") then
            error(quit_message);
        end
        lsSleep(10);
    end
    return count;
end

function SetupLureGroup()
    TLures = {};
    LastLure = "";

    if LastLure ~= nil then
        lureCounter = 0;
        for i = 1, #Lures, 1 do
            lureList = findText(Lures[i]);
            if lureList then
                -- Add Lure
                lureCounter = lureCounter + 1;
                statusScreen("Indexing Lures [" .. lureCounter .. "]\n" .. Lures[i], nil, 0.7);
                lsSleep(50);
                table.insert(TLures, Lures[i]);
            end
        end
    end
    lsSleep(100);
    return TLures;
end

function getLureList()
    for i = 1, #Lures, 1 do -- start from first line
        Lure = findText(Lures[i]);
        if Lure then
            return Lures[i]
        end
    end
end

function UseLure()
    checkBreak();
    if #TLures == 0 then
        if not muteSoundEffects then
            lsPlaySound("fail.wav");
        end
        error 'Can\'t find any lures on the pinned window. Did you run out of lures?'
    end

    CurrentLure = PlayersLures[CurrentLureIndex];

    if #TLures == 1 then
        QCurrentLure = CurrentLure;
        QCurrentLureIndex = CurrentLureIndex;
    elseif LostLure == 1 and not lastCast then
        -- Do Nothing, continue...
    else
        QCurrentLure = PlayersLures[QCurrentLureIndex];
    end

    -- Uses lure according to CurrentLureIndex, which is used in PlayersLures which contains each lure the player has.
    lsDoFrame(); -- Blank the screen so next statusScreen messages isn't mixed/obscured with previous gui_refresh info on screen
    lsSleep(10);
    if LostLure == 1 and not lastCast then
        statusScreen("Lost Lure! | " .. lastLostLure .. "\nUsing same lure again!", nil, 0.7);
        table.insert(lostlure_log, lastLostLure .. " (" .. lastLostLureType .. ")");
        lsSleep(1000);
    elseif LostLure == 1 then
        statusScreen("Lost Lure! | " .. lastLostLure .. "\nSwitching Lures | " .. QCurrentLure, nil, 0.7);
        table.insert(lostlure_log, lastLostLure .. " (" .. lastLostLureType .. ")");
        lsSleep(1000);
    else
        statusScreen("Switching Lures | " .. QCurrentLure, nil, 0.7);
        lsSleep(750);
    end

    srReadScreen();
    -- Refresh the fishing menu and re-index the new lure order
    fishingWindow = findText("Fishing Lure");
    safeClick(fishingWindow[0], fishingWindow[1])

    lsDoFrame();
    statusScreen("Indexing Lures ...", nil, 0.7);
    checkBreak()
    srReadScreen();
    getLureList();

    if QCurrentLureIndex > 30 then
        srClickMouseNoMove(down[0] + 5, down[1] + 5);
        lsSleep(200);
    elseif #PlayersLures > 30 then
        if up then
            srClickMouseNoMove(up[0] + 5, up[1] + 5);
        end
        lsSleep(200);
    end

    srReadScreen();

    if LostLure == 1 and not lastCast then
        lure = findText(PlayersLures[CurrentLureIndex]);
    else
        lure = findText(PlayersLures[QCurrentLureIndex]);
    end

    LostLure = 0;

    if lure then
        for i = 1, #Lure_Types, 1 do
            test = findText(Lure_Types[i]);
            if test then
                LureType = Lure_Types[i];
                if not muteSoundEffects then
                    lsPlaySound("high_rise.wav");
                end
                --Click it!
                srClickMouseNoMove(test[0]+12,test[1]+5);
                break;
            end
        end

        srClickMouseNoMove(lure[0] + 12, lure[1] + 5);
        lsSleep(200);
        srReadScreen();
        local deselect = findText("Deselect as preferred Fishing Lure");
        if deselect then
            local escape = "\27"
            srKeyEvent(escape) -- Hit ESC to close out possible pinned menu.
        else
            local t = waitForText("Select as preferred Fishing Lure", 500)
            clickText(t);
        end
        lsSleep(200);
    end
end

function checkIfMain(chatText)
    for j = 1, #chatText do
        if string.find(chatText[j][2], "^%*%*", 0) then
            return true;
        end
        for k, v in pairs(Chat_Types) do
            if string.find(chatText[j][2], k, 0, true) then
                return true;
            end
        end
    end
    return false;
end

function ChatReadFish(value)
    -- Find the last line of chat
    local chatText = getChatText();
    if value ~= nil then
        numCaught, fishType = string.match(lastLine, "(%d+) deben ([^.]+)%."); -- Read next to last line of main chat
    else
        fishType = string.match(lastLine, "Caught [%w ']+ ([^.]+)%."); -- Read last line of main chat
    end
    if fishType then
        Sfish = string.gsub(fishType, "%W", "");
        if value ~= nil then
            SNum = numCaught
            GrandTotaldb = GrandTotaldb + SNum
        end
    end
    if value ~= nil then
        logMessage = ("[" .. CurrentLure .. " (" .. LureType .. ")] " .. Sfish .. " (" .. SNum .. "db)");
        logType = "seasonal"
    else
        logMessage = ("[" .. CurrentLure .. " (" .. LureType .. ")] " .. Sfish);
        logType = "common"
    end
    return logMessage, logType;
end

function findchat()
    -- Find the last line of chat
    checkBreak();
    srReadScreen();
    chatText = getChatText();

    local onMain = checkIfMain(chatText);
    if not onMain then
        if not muteSoundEffects then
            lsPlaySound("timer.wav");
        end
    end

    -- Wait for Main chat screen and alert user if its not showing
    while not onMain do
        checkBreak();
        srReadScreen();
        chatText = getChatText();
        onMain = checkIfMain(chatText);
        sleepWithStatus(500,
            "Looking for Main chat screen...\n\nMake sure main chat tab is showing and that the window is sized, wide enough, so that no lines wrap to next line..",
            nil, 0.7);
    end

    while #chatText < 2 do
        checkBreak();
        srReadScreen();
        chatText = getChatText();
        sleepWithStatus(500,
            "Error: We must be able to read at least the last 2 lines of chat!\n\nCurrently we only see " .. #chatText ..
                " lines ...\n\nYou can also type something in main chat or manually fish, once or twice, to bypass this error!",
            nil, 0.7);
    end

    -- Read last line in chat
    lastLine = chatText[#chatText][2];
    lastLineParse = string.sub(lastLine, string.find(lastLine, "m]") + 3, string.len(lastLine));

    -- Read next to last line in chat
    lastLine2 = chatText[#chatText - 1][2];
    lastLineParse2 = string.sub(lastLine2, string.find(lastLine2, "m]") + 3, string.len(lastLine2));

    gui_refresh();
end

function findClockInfo()
    srReadScreen();
    coordinates = findCoords()
    if not coordinates then
        error("ATITD clock not found. Please post a screenshot in discord");
    else
        coordX = coordinates[0];
        coordY = coordinates[1];
        coordinates = coordX .. ", " .. coordY
    end

    fetchTime = getTime(1);
    year, date, time = fetchTime:match('(.*), (.*), (.*)')
end

function gui_refresh()
    checkBreak();

    if GrandTotalCaught < 10 then
        last10 = GrandTotalCaught .. "/10";
    elseif GrandTotalCaught > 10 then
        last10 = "10/" .. GrandTotalCaught
    else
        last10 = 10;
    end

    -- Stats (On Screen Display)
    -- CurrentLureIndex  out of  PlayersLures
    winsize = lsGetWindowSize();

    if #PlayersLures == 0 then
        if not muteSoundEffects then
            lsPlaySound("fail.wav");
        end
        error 'Can\'t find any lures on the pinned window. Did you run out of lures?';
    elseif #PlayersLures == 1 then
        CurrentLureIndex = 1;
        QCurrentLureIndex = 1;

    elseif CurrentLureIndex > #PlayersLures then
        CurrentLureIndex = #PlayersLures;
        QCurrentLureIndex = 1;
    end

    local y = 2;
    CurrentLure = PlayersLures[CurrentLureIndex];
    QCurrentLure = PlayersLures[QCurrentLureIndex];
    --lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, 0xc0c0ffff, date .. " | " .. time .. " | " .. coordinates);
    nextLureChange = TotalCasts + 1 - castcount
    nextLureChangeMessageColor = 0xc0ffffff;

    if nextLureChange - 1 <= 0 and LockLure then
        nextLureChangeMessageColor = 0xffff40ff;
        nextLureChangeMessage = "< LURE LOCKED! >  Unlock when ready to change Lure!";
    elseif nextLureChange - 1 <= 0 and not LockLure then
        nextLureChangeMessageColor = 0xffff40ff;
        nextLureChangeMessage = "0 casts remaining ... Lure will change after this cast!";
    elseif LockLure then
        nextLureChangeMessageColor = 0xffff40ff;
        nextLureChangeMessage = "< LURE LOCKED! >  " .. nextLureChange - 1 .. " casts remaining ...";
    else
        nextLureChangeMessage = nextLureChange - 1 .. " casts remaining until Next Lure change!";
    end

    y = y + 12;
    lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, 0xc0ffc0ff, "Current Lure: " .. CurrentLureIndex .. " of " ..
        #PlayersLures .. "   " .. CurrentLure .. " (" .. LureType .. ")");
    y = y + 12;
    lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, nextLureChangeMessageColor, nextLureChangeMessage);
    y = y + 14;
    lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, 0xfcad86ff, "Cast Timer: " .. round(castWait / 1000, 1) .. " s");
    y = y + 12;
    lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, 0xfbc3abff,
        "Last Timer: " .. round(lastCastWait / 1000, 1) .. " s");
    lsSetCamera(0, 0, lsScreenX * 1.6, lsScreenY * 1.6);

    if lsButtonText(160, y + 20, 0, 20, 0xffffffff, "-") then
        QCurrentLureIndex = QCurrentLureIndex - 1;
        if QCurrentLureIndex < 1 then
            QCurrentLureIndex = #PlayersLures;
        end
    end

    if lsButtonText(187, y + 20, 0, 20, 0xffffffff, "+") then
        QCurrentLureIndex = QCurrentLureIndex + 1
        if QCurrentLureIndex > #PlayersLures then
            QCurrentLureIndex = 1;
        end
    end

    lsSetCamera(0, 0, lsScreenX * 1.0, lsScreenY * 1.0);

    lsPrintWrapped(137, y - 5, 0, lsScreenX - 20, 0.5, 0.5, 0xfFFFFFff, "Next Lure (" .. QCurrentLureIndex .. "):");

    if skipLure or ((TotalCasts + 1 - castcount) <= 1 and not LockLure) then
        lsPrintWrapped(209, y - 5, 0, lsScreenX - 20, 0.5, 0.5, 0xffffc0ff, QCurrentLure);
    else
        lsPrintWrapped(209, y - 5, 0, lsScreenX - 20, 0.5, 0.5, 0xc0ffffff, QCurrentLure);
    end
    y = y + 13;
    lsPrintWrapped(10, y, 0, lsScreenX - 20, 0.5, 0.5, 0xffffc0ff, "Last " .. last10 .. " Fish Caught:\n");

    -- Reset this string before showing last10 or allcaught fish below. Else the entries will multiply exponetially with entries from previous loops/call to this function
    last10caught = "";
    allcaught = "";
    lostlures = "";

    if #gui_log_fish > 10 then
        table.remove(gui_log_fish, 11);
    end
    for i = 1, #gui_log_fish, 1 do
        lsPrintWrapped(10, y + (14 * i), 0, lsScreenX - 18, 0.5, 0.5, 0xffffdfff, gui_log_fish[i]);
    end

    for i = 1, #gui_log_fish2, 1 do
        allcaught = allcaught .. gui_log_fish2[i] .. "\n";
    end

    for i = 1, #lostlure_log, 1 do
        lostlures = lostlures .. lostlure_log[i] .. "\n";
    end

    lsPrintWrapped(115, winsize[1] - 46, 0, lsScreenX - 20, 0.5, 0.5, 0xffffffff, "Odd Fish Seen: " .. GrandTotalOdd);
    lsPrintWrapped(115, winsize[1] - 34, 0, lsScreenX - 20, 0.5, 0.5, 0xffffffff,
        "Unusual Fish Seen: " .. GrandTotalUnusual);
    lsPrintWrapped(115, winsize[1] - 22, 0, lsScreenX - 20, 0.5, 0.5, 0xffffffff,
        "Strange Fish Seen: " .. GrandTotalStrange);
    lsPrintWrapped(10, winsize[1] - 94, 0, lsScreenX - 20, 0.5, 0.5, 0xffff40ff,
        "- - - - - - - - - - - - - - - - - - - -");
    lsPrintWrapped(10, winsize[1] - 82, 0, lsScreenX - 20, 0.5, 0.5, 0xc0ffc0ff,
        "Lures Switched: " .. GrandTotalLuresUsed - 1);
    if lastLostLure ~= "" then
        lsPrintWrapped(10, winsize[1] - 70, 0, lsScreenX - 20, 0.5, 0.5, 0xff8080ff, "Lures Lost: " ..
            GrandTotalLostLures .. "   -  Last: " .. lastLostLure .. " (" .. lastLostLureType .. ")");
    else
        lsPrintWrapped(10, winsize[1] - 70, 0, lsScreenX - 20, 0.5, 0.5, 0xff8080ff,
            "Lures Lost: " .. GrandTotalLostLures);
    end
    lsPrintWrapped(10, winsize[1] - 58, 0, lsScreenX - 20, 0.5, 0.5, 0xffff40ff,
        "- - - - - - - - - - - - - - - - - - - -");
    lsPrintWrapped(10, winsize[1] - 46, 0, lsScreenX - 20, 0.5, 0.5, 0xc0ffffff, "Completed Casts: " .. GrandTotalCasts);
    lsPrintWrapped(10, winsize[1] - 34, 0, lsScreenX - 20, 0.5, 0.5, 0xff8080ff, "Failed Catches: " .. GrandTotalFailed);
    lsPrintWrapped(10, winsize[1] - 22, 0, lsScreenX - 20, 0.5, 0.5, 0xffffc0ff,
        "Fish Caught: " .. GrandTotalCaught .. " (" .. math.floor(GrandTotaldb) .. "db)");
    lsSetCamera(0, 0, lsScreenX * 1.6, lsScreenY * 1.6);

    if lsButtonText(lsScreenX + 50, lsScreenY + 20, 0, 120, 0x6666FFff, "Options") then
        lsDoFrame();
        setResume = true;
        setOptions();
    end

    if lsButtonText(lsScreenX + 50, lsScreenY + 50, 0, 120, 0xFF0000ff, "End Script") then
        error(quit_message);
    end

    if skipLure or ((TotalCasts + 1 - castcount) <= 1 and not LockLure) then
        skipLureText = "Next Lure";
        skipLureTextColor = 0xffff40ff;
    else
        lastCast = false;
        skipLureText = "Next Lure";
        skipLureTextColor = 0xFFFFFFff;
    end

    if skipLure or ((TotalCasts + 1 - castcount) <= 0 and not LockLure) then
        lastCast = true;
    else
        lastCast = false;
    end

    if not finishUp then
        if lsButtonText(lsScreenX + 50, lsScreenY + 120, 0, 120, 0xffbb80ff, "Finish Up") then
            finishUp = true;
        end
    else
        if lsButtonText(lsScreenX + 50, lsScreenY + 120, 0, 120, 0xff8080ff, "Cancel ...") then
            finishUp = false;
        end
    end

    if lsButtonText(lsScreenX + 50, lsScreenY + 150, 0, 120, skipLureTextColor, skipLureText) then
        if skipLure then
            skipLure = false;
        else
            skipLure = true;
            LockLure = false;
        end
    end

    if LockLure then
        LockLureColor = 0xffff40ff;
        LockLureText = "Cancel Lock!";
    else
        LockLureColor = 0xFFFFFFff;
        LockLureText = "Lock Lure";
    end

    if lsButtonText(lsScreenX + 50, lsScreenY + 180, 0, 120, LockLureColor, LockLureText) then

        if LockLure then
            LockLure = false;
        else
            LockLure = true;
            skipLure = false;
        end
    end

    if #lostlure_log == 0 then
        lostlures = "*** No lures lost! ***";
    end

    if #gui_log_fish2 == 0 then
        allcaught = "*** No fish caught! ***";
    end

    if writeStats then
        findClockInfo()
        WriteFishStats(
            "Note this report is overwritten every time the macro runs. The stats are for last fishing session only!\n"
            .."You can safely delete this file, but it will be created the next time macro runs!"
            .."\n\n\nLast coordinates: " ..coordinates.. "\n----------------------------------\nOdd Fish Seen: "
            ..GrandTotalOdd.."\nUnusual Fish Seen: "..GrandTotalUnusual.."\nStrange Fish Seen: "..GrandTotalStrange
            .."\n----------------------------------\nLures Clicked: "..GrandTotalLuresUsed.."\nLures Lost: "
            ..GrandTotalLostLures.."\n----------------------------------\nCasts: "..GrandTotalCasts
            .."\nFailed Catches: "..GrandTotalFailed.."\nFish Caught: "..GrandTotalCaught.." ("
            ..math.floor(GrandTotaldb).."db)\n----------------------------------\n\nAll lures lost this Session:\n\n"
            ..lostlures.. "\n\n\nAll fish caught this Session:\n\n"..allcaught);
    end

    lsDoFrame();
    lsSleep(10);
end

function doit()

    askForWindow("MAIN chat tab MUST be showing and wide enough so that each line doesn't wrap.\n\n" ..
                     "Right click the 'Fishing Lure' menu in your inventory and pin this window.\n\n" ..
                     "History will be recorded in FishLog.txt and stats in FishStats.txt.");

    setOptions();
    PlayersLures = SetupLureGroup(); -- Fetch the list of lures from pinned lures window
    lsSleep(1000); -- Just a delay to let the sound effect finishing playing, not needed...

    while 1 do
        checkBreak();
        srReadScreen();
        cast = srFindImage("Fishing/fishicon.png", 100);
        OK = srFindImage("OK.png");
        if ignoreOK then
            OK = nil; -- We got a popup box while examining isis ship pieces recently, prevent potential reindexing lures (No lure found, refreshing.. Below)
        end
        lsSleep(100)

        if not cast then
            if not muteSoundEffects then
                lsPlaySound("timer.wav");
            end
        end

        while not cast do
            checkBreak();
            srReadScreen();
            cast = srFindImage("fishing/fishicon.png", 100);
            sleepWithStatus(500, "Can\'t find Fishing icon ...");
        end

        if castcount == 0 or OK or skipLure then
            castcount = 1;
            skipLure = false;

            if #PlayersLures > 1 then
                LockLure = false;
            else
                LockLure = true;
            end

            if #PlayersLures > 1 and not OK then
                UseLure(); -- Switch Lures
                GrandTotalLuresUsed = GrandTotalLuresUsed + 1;
            end

            if OK then
                srClickMouseNoMove(OK[0] + 5, OK[1] + 3); -- Close the popup OK button
                sleepWithStatus(1500, "No " .. QCurrentLure .. " lure found!\nRefreshing lure list ...", nil, 0.7)
                PlayersLures = SetupLureGroup();
                if QCurrentLureIndex > #PlayersLures or QCurrentLureIndex == 1 then
                    QCurrentLureIndex = 2;
                    CurrentLureIndex = 1;

                end
                UseLure(); -- Switch Lures
            else
                CurrentLureIndex = QCurrentLureIndex;
                QCurrentLureIndex = QCurrentLureIndex + 1;
            end

            if QCurrentLureIndex > #PlayersLures and not OK then
                -- Last Lure, Prepare to go to first lure in list ...
                QCurrentLureIndex = 1;
                CurrentLureIndex = #PlayersLures;
            end

            -- update log
            gui_refresh();

        elseif LostLure == 1 then
            UseLure(); -- Equip Same Lure again

        elseif castcount > TotalCasts and not LockLure then
            -- Reset
            castcount = 0;

        else

            -- Cast
            checkBreak();
            castWait = 0;
            findchat();
            lastLineFound = lastLineParse; -- Record last line before casting
            lastLineFound2 = lastLineParse2; -- Record next to last line before casting
            safeClick(cast[0] + 3, cast[1] + 3);
            lsSleep(200);
            srReadScreen();
            local cancel = srFindImage("cancel.png")
            if cancel then
                castcount = 0;
                safeClick(cancel[0], cancel[1])
                lsSleep(1500); -- Wait for the fishing animation to finish
                UseLure(); -- The lure broke, switch to the next one
            end

            startTime = lsGetTimer();
            ignoreOK = nil;

            while 1 do
                findchat();
                OK = srFindImage("OK.png");
                writeLastTwoLines = nil;
                noWriteLog = nil;
                overweight = nil;
                skipOkOnce = nil; -- Helps prevent premature break, from OK box while checking Isis ship debris
                lsSleep(100);
                checkBreak();
                castWait = (lsGetTimer() - startTime);
                gui_refresh();

                if not muteSoundEffects and castWait / 1000 > 2.5 and castWait / 1000 < 2.7 then
                    lsPlaySound("fishingreel.wav");
                end

                for k, v in pairs(Isis_List) do
                    if string.find(lastLine, k, 0, true) then
                        -- If we get a message in chat from examining test of isis ship pieces, then ignore message and ignore popup box
                        -- This causes a short OK popup "Examining Relic", but then closes by itself. We don't want to confuse this for a popup from missing lure; ignore
                        lastLineFound = lastLineParse; -- Re-Record last line (with new message)
                        lastLineFound2 = lastLineParse2; -- Re-Record next to last line (with new message)
                        ignoreOK = 1;
                        noWriteLog = 1;
                    end
                end

                if OK then
                    skipOkOnce = 1; -- Prevents a premature break below from OK box while Examining Isis ship pieces, until next loop. Give a chance for ignoreOK to get recognized
                end

                for k, v in pairs(Ignore_List) do
                    if string.find(lastLine, k, 0, true) or not string.find(lastLine, "^%*%*", 0) then
                        -- If we get a message defined in Ignore_List (already fishing, item is from a forge, or no ** (player is speaking in main chat), then ignore
                        lastLineFound = lastLineParse; -- Re-Record last line (with new message)
                        lastLineFound2 = lastLineParse2; -- Re-Record next to last line (with new message)
                        noWriteLog = 1;
                    end
                end

                if (lastLineFound2 ~= lastLineParse2 or lastLineFound ~= lastLineParse) or
                    (OK and not ignoreOK and not skipOkOnce) or ((lsGetTimer() - startTime) > 20000) then
                    lastCastWait = castWait;
                    break
                end
            end -- end while 1 do

            castcount = castcount + 1;
            GrandTotalCasts = GrandTotalCasts + 1;

            -- Parse Chat
            CurrentLure = PlayersLures[CurrentLureIndex];
            caughtFish = false;

            for k, v in pairs(Chat_Types) do
                if string.find(lastLine, k, 0, true) then
                    if v == "overweight" then
                        if string.match(lastLine2, "(%d+) deben ([^.]+)%.") then
                            caughtFish = true; -- This will force it to parse the next to last line, instead of last line for any caught fish
                        end
                    end

                    if v == "achievement" then
                        -- If last message was 'You have achieved: Caught a blah blah', then caughtFish = true, parse the next to last line for fish caught
                        --  Also set bool to record both lines in log
                        writeLastTwoLines = 1;
                        caughtFish = true; -- This will force it to parse the next to last line, instead of last line for any caught fish
                    end

                    if v == "alreadyfishing" or (OK and not ignoreOK) then
                        castcount = castcount - 1;
                        GrandTotalCasts = GrandTotalCasts - 1;
                    end

                    if v == "lostlure" then
                        if not muteSoundEffects then
                            lsPlaySound("boing.wav");
                        end
                        lastLostLure = CurrentLure;
                        lastLostLureType = LureType;
                        GrandTotalLostLures = GrandTotalLostLures + 1;
                        LostLure = 1;
                        -- Reset, skip to next lure
                        -- castcount=0;
                    end

                    if v == "odd" then
                        GrandTotalOdd = GrandTotalOdd + 1;
                    end

                    if v == "strange" then
                        GrandTotalStrange = GrandTotalStrange + 1;
                    end

                    if v == "unusual" then
                        GrandTotalUnusual = GrandTotalUnusual + 1;
                    end

                    if v == "caught" or caughtFish then
                        if v == "caught" and string.match(lastLine, "Caught a (%d+) deben ([^.]+)%.") then
                            caughtFish = true;
                            Fish = ChatReadFish(1); -- Parse last line of main chat
                        elseif v == "caught" and string.match(lastLine, "Caught [%w ']+ ([^.]+)%.") then
                            caughtFish = true;
                            Fish = ChatReadFish(); -- Parse next to last line of main chat

                            if not fishType then
                                caughtFish = nil;
                            else
                                overweight = 1;
                            end
                        end

                        if caughtFish then
                            -- Last 10 fish caught that displays on GUI
                            if logType == "common" and displayCommon then
                                GrandTotalCaught = GrandTotalCaught + 1
                                addlog = Sfish .. " | " .. CurrentLure
                                table.insert(gui_log_fish, 1, addlog);
                            elseif logType == "seasonal" then
                                GrandTotalCaught = GrandTotalCaught + 1
                                addlog = Sfish .. " (" .. SNum .. "db) | " .. CurrentLure
                                table.insert(gui_log_fish, 1, addlog);
                            end
                            -- All fish caught that displays in fishstats.txt
                            table.insert(gui_log_fish2, addlog);
                            FishType = Sfish;
                            if SkipCommon == true and LockLure == false then
                                if FishType == "Abdju" or FishType == "Chromis" or FishType == "Catfish" or FishType ==
                                    "Carp" or FishType == "Oxyrynchus" or FishType == "Perch" or FishType == "Phagrus" or
                                    FishType == "Tilapia" then
                                    castcount = 0;
                                end
                            end
                        end
                    end
                    -- Add more if v == "something" then statements here if needed
                end
                gui_refresh();
            end

            if not caughtFish then
                GrandTotalFailed = GrandTotalFailed + 1;
            end

            if v == "lure" or v == "alreadyfishing" or noWriteLog or not string.find(lastLine, "^%*%*", 0) then
                -- Do nothing
            elseif overweight then
                if LogFails then
                    findClockInfo()
                    WriteFishLog("[" .. date .. ", " .. time .. "] [" .. coordinates .. "] [" .. CurrentLure .. " (" ..
                                    LureType .. ")] " .. lastLineParse2 .. "\n");
                end
            elseif writeLastTwoLines then
                if LogFails then
                    findClockInfo()
                    WriteFishLog("[" .. date .. ", " .. time .. "] [" .. coordinates .. "] [" .. CurrentLure .. " (" ..
                                    LureType .. ")] " .. lastLineParse2 .. "\n");
                    WriteFishLog("[" .. date .. ", " .. time .. "] [" .. coordinates .. "] [" .. CurrentLure .. " (" ..
                                    LureType .. ")] " .. lastLineParse .. "\n");
                end
            elseif LogFails then
                findClockInfo()
                WriteFishLog("[" .. date .. ", " .. time .. "] [" .. coordinates .. "] [" .. CurrentLure .. " (" ..
                                 LureType .. ")] " .. lastLineParse .. "\n");
            end

            gui_refresh();
        end
        if finishUp then
            lsPlaySound("Complete.wav");
            error("Finished up, per your request!");
        end
        gui_refresh();
        if AutoFillet then
            filletFish(); -- Search for "All Fish" pinned up. If so, fillet.
            lsSleep(400); -- Required to avoid constant "already fishing" spam.
        end
    end
end

function round(num, numDecimalPlaces)
    local mult = 10 ^ (numDecimalPlaces or 0)
    return math.floor(num * mult + 0.5) / mult
end

function filletFish()
    srReadScreen();
    fillet = findText("All Fish");
    if fillet then
        clickAllText("All Fish");
    else
        clickAllImages("WindowEmpty.png", 5, 5, nil, nil);
    end
end