module patch.reflow;

import core.stdc.string : memcpy;
import core.stdc.stdlib : malloc, free;
import std.algorithm : min, max;

import patches : isPatchEnabled, HISTSIZE;
import st : term, Glyph, Line, IS_SET, tclearregion, tcursor, tswapscreen;
import st : sel, defaultfg, defaultbg, kscrolldown, Arg, ATTR_WRAP;

// Define constants
enum MODE_ALTSCREEN = 1 << 2;
enum ATTR_NULL = 0;
enum ATTR_SET = 1 << 15;

// Cursor operations
enum {
    CURSOR_SAVE = 0,
    CURSOR_LOAD = 1
}

// Memory functions
void* xmalloc(size_t size) {
    void* p = malloc(size);
    if (!p) {
        import core.stdc.stdlib : exit;
        exit(1);
    }
    return p;
}

void xfree(void* p) {
    if (p) free(p);
}

// Define tiswrapped function
bool tiswrapped(Line line) {
    return (line[term.col - 1].mode & ATTR_WRAP) != 0;
}

static if (isPatchEnabled!"REFLOW_PATCH") {
    static if (isPatchEnabled!"SIXEL_PATCH") {
        import st : ImageList;
        
        // Define tdeleteimages stub
        void tdeleteimages() {
            // TODO: Implement when sixel patch is fully ported
        }
    }

    void tloaddefscreen(int clear, int loadcursor) {
        int col, row, alt = IS_SET(MODE_ALTSCREEN);

        if (alt) {
            if (clear) {
                tclearregion(0, 0, term.col-1, term.row-1);
                static if (isPatchEnabled!"SIXEL_PATCH") {
                    tdeleteimages();
                }
            }
            col = term.col;
            row = term.row;
            tswapscreen();
        }
        if (loadcursor)
            tcursor(CURSOR_LOAD);
        if (alt)
            tresizedef(col, row);
    }

    void tloadaltscreen(int clear, int savecursor) {
        int col, row, def = !IS_SET(MODE_ALTSCREEN);

        if (savecursor)
            tcursor(CURSOR_SAVE);
        if (def) {
            col = term.col;
            row = term.row;
            Arg arg = Arg(term.scr);
            kscrolldown(&arg);
            tswapscreen();
            tresizealt(col, row);
        }
        if (clear) {
            tclearregion(0, 0, term.col-1, term.row-1);
            static if (isPatchEnabled!"SIXEL_PATCH") {
                tdeleteimages();
            }
        }
    }

    void selmove(int n) {
        sel.ob.y += n;
        sel.nb.y += n;
        sel.oe.y += n;
        sel.ne.y += n;
    }

    void tclearglyph(Glyph* gp, int usecurattr) {
        if (usecurattr) {
            gp.fg = term.c.attr.fg;
            gp.bg = term.c.attr.bg;
        } else {
            gp.fg = defaultfg;
            gp.bg = defaultbg;
        }
        gp.mode = ATTR_NULL;
        gp.u = ' ';
    }

    static if (isPatchEnabled!"SIXEL_PATCH") {
        void treflow_moveimages(int oldy, int newy) {
            ImageList* im;

            for (im = term.images; im; im = im.next) {
                if (im.y == oldy)
                    im.reflow_y = newy;
            }
        }
    }

    // TODO: Implement the full treflow function
    void treflow(int col, int row) {
        // This is a complex function that needs full implementation
        // For now, providing a stub
    }

    void tresizedef(int col, int row) {
        // TODO: Implement
    }

    void tresizealt(int col, int row) {
        // TODO: Implement
    }
}