#include "spiel.h"

void Say(Co co,Let* msg,Let col,Let row,Color cl){
    CursesSay(co,msg,col,row,cl);
}

void User(Co co, Routine next){
    Routine routines[] = {
        Wait,
        Control,
        Render,
        0
    };
    Deed(co,routines);
    if (Pressed(co,'q'))
    Next(co,End);
    else
    Next(co,next);
}

Color Palette(Let ch){
    switch(ch){
        case 'g':
            return TG;
            break;
        case 'b':
            return TB;
            break;
        case 'r':
            return TR;
            break;
        case 'p':
            return TP;
            break;
        case 'c':
            return TC;
            break;
        case 'y':
            return TY;
            break;
        case 'k':
            return TK;
            break;
        case 'w':
            return TW;
            break;
    }       
    return T;
}

Let Bg(Co co, Let col, Let row){
    if (col >= W)
    return '#';

    if (row >= H)
    return '#';

    if (col >= co->llection[MMAND][BGCOLS])
    return '#';

    if (row >= co->llection[MMAND][BGROWS])
    return '#';

    return co->mposition[row][col];
}

void BgPlot(Co co, Let col, Let row){
    Let cs = Bg(co,col,row);
    Let ch = ' ';
    switch(cs){
        case '#': ch = Pixel; break;
        case '|': ch = Vln; break;
        case '-': ch = Hln; break;
        case '+':
            {
                Let c[] = { 
                /* 0 0   */ '+','+','+',Urc,
                /* 0 1   */ '+',Vln,Lrc,Lft,
                /* 1 0   */ '+',Ulc,Hln,Bft,
                /* 1 1   */ Llc,Rft,Uft,Pln,
                /*          00  01  10  11 */0};
                Let i = 15;
                if (Bg(co,col,row-1)!='|'){ i = i-1;}
                //if (Bg(co,col+1,row)!='-'){ i = i-2;}
                //if (Bg(co,col,row+1)!='|'){ i = i-4;}
                if (Bg(co,col-1,row)!='-'){ i = i-8;}
                ch = c[i];
            }
            ch = Pln;
            break;
    }
    Let cl = Palette(cs);
    CursesPlot(ch,col,row,cl);
}

void ClrSpr(Co co){
    for (int i=0; i<MAX; i++)
    if (co->llection[SPRCHR][i] != 0)
    co->llection[SPRCHR][i] = 0;
}

void Render(Co co){
    // draw sprites
    
    for (int i=0; i<MAX; i++)
    if (co->llection[SPRCHR][i] != 0){
        Let c = co->llection[SPRCHR][i];
        Let x = co->llection[SPRX][i];
        Let y = co->llection[SPRY][i];
        Let cl = co->llection[SPRCLR][i];
        Let ox = co->llection[GHSTX][i];
        Let oy = co->llection[GHSTY][i];
        Let bg = Bg(co,x,y);
        // if sprite had moved, erase last position
        if (x != ox || y != oy){
            BgPlot(co,ox,oy);
        }
        // if sprite is ignored. dont generate shadow
        if (c == ' '){
            co->llection[GHSTX][i] = x;
            co->llection[GHSTY][i] = y;
            //co->llection[SPRCHR][i] = 0;
        }
        // simply draw it
        else{
            if (cl % Black == T)
            cl = cl + Palette(Bg(co,x,y));
            CursesPlot(c,x,y,cl);
            // update the ghost
            co->llection[GHSTX][i] = x;
            co->llection[GHSTY][i] = y;
        }
    }

    CursesRefresh(co);
}

Let Clock(Co co){
    return co->llection[MMAND][Clck];
}

Let Pressed(Co co, Let key){
    if (key >= 'a')
    key = key - 'a' + 'A';
    if (key < MAX)
    return co->llection[KEYS][key];
    return 0;
}

void Plot(Co co,Let id, Let ch, Let x, Let y, Color cl){
    co->llection[SPRCHR][id] = ch;
    co->llection[SPRX][id] = x;
    co->llection[SPRY][id] = y;
    co->llection[SPRCLR][id] = cl;
}

void Draw(Co co, Let ** image){
    co->mposition = image;
    for (Let row=0; image[row] != 0; row++)
    for (Let col=0; image[row][col] != 0; col++){
        co->llection[MMAND][BGCOLS] = col+1;
        co->llection[MMAND][BGROWS] = row+1;
        BgPlot(co,col,row);
    }
}
Let X(Co co,Let id){
    return co->llection[SPRX][id];
}
Let Y(Co co,Let id){
    return co->llection[SPRY][id];
}

Let Collide(Co co,Let first, Let second){
    if (co->llection[SPRX][first] == co->llection[SPRX][second])
    if (co->llection[SPRY][first] == co->llection[SPRY][second])
    return 1;
    return 0;
}

void Lvl(Co co, Let ** level){
    ClrSpr(co);
    // pre init 
    for (Let i=0;co->nstant[MRKS][i]!=0;i++)
    Plot(co,co->nstant[FGRS][i],' ',0,0,T);

    // init position if found
    for (Let row=0;row<H;row++)
    for (Let col=0;col<W;col++)
    for (Let i=0;co->nstant[MRKS][i]!=0;i++)
    if (Bg(co,col,row) == co->nstant[MRKS][i])
    Plot(co,co->nstant[FGRS][i],'_',col,row,T);
}

Let At(Co co, Let col, Let row){
    Let cell = Bg(co,col,row);

    for (Let i=0;co->nstant[MRKS][i]!=0;i++)
    if (cell == co->nstant[MRKS][i])
    return ' ';

    return cell;
}


