//render распространяется под ЖоПЛv8 и ниипет.
//вы видели код, теперь вы мне должны.

#include <swilib.h>
#include "conf_loader.h"
#include "cpumon.h"

extern TSensor *Sensors[];
extern int nSensors;
extern TSensor *TexSensors[];
extern int nTexSensors;
extern int uiWidth, uiHeight;
extern int uiBits;
extern const RECT position;
extern const int cfgRender;
extern const int cfgTextRender;
extern IMGHDR img1;
extern char* img1_bmp;

int Color2ColorByRenderBit(const char *color)
{
    switch (uiBits) {
    case 0:
        return  RGB8 (color[0],color[1],color[2]);
    case 1:
        return  RGB16(color[0],color[1],color[2]);
    default:
        return RGB24(color[0],color[1],color[2],color[3]);
    }
}

static void SetColorByRenderBit(const int index,const int color)
{
    switch (uiBits) {
    case 0:
        img1_bmp[index]=color;
        break;
    case 1:
        ((short *)img1_bmp)[index]=color;
        break;
    case 2:
        ((int *)img1_bmp)[index]=color;
        break;
    }
}

static int GetColorByRenderBit(const int index)
{
    switch (uiBits) {
    case 0:
        return img1_bmp[index];
    case 1:
        return ((unsigned short *)img1_bmp)[index];
    case 2:
    default:
        return ((int *)img1_bmp)[index];
    }
}

int min(int a,int b)
{
    if (a<b) return a;
    else return b;
}

int min3(int a,int b,int c)
{
    int d=min(a,b);
    if (c<d) return c;
    else return d;
}

int max(int a,int b)
{
    if (a>b) return a;
    else return b;
}

int max3(int a,int b,int c)
{
    int d=max(a,b);
    if (c>d) return c;
    else return d;
}

static int RenderBit2Transparent[3]= {0xc0,0xe000,0x0};
static int hhh[NSENSORS];

static int GetMinSensor(const int x, const int sY,
                        int *minColor, int *minSolidColor)
{
    int minY=0x7fffffff,minYSC=0x7fffffff;
    *minSolidColor=RenderBit2Transparent[uiBits];
    for(int n=0; n<nSensors; n++) {
        int h=hhh[n];
        int t=Sensors[n]->type;
        int v=Sensors[n]->getValue(x,h);
        if (t==2) { //line
            int v1,v2,minv,maxv;
            if (x>0) {
                v1=(Sensors[n]->getValue(x-1, h==0 ? uiWidth-1 : h-1)+v)/2;
            } else v1=v;
            if (x<uiWidth-1) {
                v2=(Sensors[n]->getValue(x+1, (h>=uiWidth-1) ? 0 : h+1)+v)/2;
            } else v2=v;
            minv=min3(v1,v,v2);
            if (sY<minv) {
                t=1;  //doted
                v=minv;
            } else {
                maxv=max3(v1-1,v,v2-1);
                v=maxv;
                if (sY<maxv) {
                    t=3;  //solid
                } else {
                    t=1;  //doted
                }
            }
        }
        if (sY<v) {
            if (v<minY) {
                minY=v;
                *minColor=Sensors[n]->getColor(x,h);
            }
            if ((t==3)&&(v<minYSC)) {
                minYSC=v;
                *minSolidColor=Sensors[n]->getColor(x,h);
            }
        }
    }
    return minY;
}

void render_BoBa()
{
    for(int n=0; n<nSensors; n++) {
        hhh[n]=Sensors[n]->hhh;
    }
    for(int x = 0; x < uiWidth; x++) {
        int y=1,yy,color,solidColor;
        while ((yy=GetMinSensor(x,y,&color,&solidColor))<=uiHeight) {
            while(y<yy) {
                SetColorByRenderBit(x + (uiHeight - y++) * uiWidth, solidColor);
            }
            SetColorByRenderBit(x + (uiHeight - y++) * uiWidth, color);
        }
        while(y<=uiHeight) {
            SetColorByRenderBit(x + (uiHeight - y++) * uiWidth, RenderBit2Transparent[uiBits]);
        }
        for(int n=0; n<nSensors; n++) {
            if(++hhh[n]>=uiWidth) hhh[n]=0;
        }
    }
}

int MidRGB(int c1, int c2)
{
    if(c1 == RenderBit2Transparent[uiBits]) return c2;
    int R =  ((((c1>>11)&0x1F)+((c2>>11)&0x1F))>>1)<<3;
    int G =  ((((c1>>5)&0x3F)+((c2>>5)&0x3F))>>1)<<2;
    int B =  (((c1&0x1F)+(c2&0x1F))>>1)<<3;
    return RGB16(R, G, B);
}

void render_Sinclair()
{
    int y1, y2, dy2, dx1, dx2;
    for(int n=0; n<nSensors; n++) {
        hhh[n]=Sensors[n]->hhh;
    }
    for(int x = 0; x < uiWidth; x++) {
        for(int y = 0; y < uiHeight; y++)
            SetColorByRenderBit(x + y * uiWidth,RenderBit2Transparent[uiBits]);
        for(int n=0; n<nSensors; n++) {
            int p=hhh[n];
            int y, ptr;
            switch(Sensors[n]->type) {
            case 1:
            case 2:
                y2 = Sensors[n]->getValue(x,p);
                if(!p)
                    y1 = Sensors[n]->getValue(uiWidth-1,uiWidth-1);
                else
                    y1 = Sensors[n]->getValue(x-1,p-1);
                if(y2>y1) {
                    dy2 = (y2-y1)>>1;
                    dx1 = y1;
                    dx2 = y1 = y1+dy2;
                } else {
                    dy2 = (y1-y2)>>1;
                    dx2 = y2;
                    y2 = dx1 = y1-dy2;
                }
                if(x)
                    while(dx1 <= y1) {
                        ptr = x-1 + (uiHeight - dx1++) * uiWidth;
                        if(!p)
                            SetColorByRenderBit(ptr, MidRGB(GetColorByRenderBit(ptr), Sensors[n]->getColor(uiWidth-1,uiWidth-1)));
                        else
                            SetColorByRenderBit(ptr, MidRGB(GetColorByRenderBit(ptr), Sensors[n]->getColor(x-1,p-1)));
                    }
                while(dx2 <= y2) {
                    ptr = x + (uiHeight - dx2++) * uiWidth;
                    SetColorByRenderBit(ptr, MidRGB(GetColorByRenderBit(ptr), Sensors[n]->getColor(x,p)));
                }
                break;
            case 3:
                y = (Sensors[n]->getValue(x,p)>uiHeight)?uiHeight:Sensors[n]->getValue(x,p);
                while(y) {
                    ptr = x + (uiHeight - y--) * uiWidth;
                    SetColorByRenderBit(ptr, MidRGB(GetColorByRenderBit(ptr), Sensors[n]->getColor(x,p)));
                }
                break;
            default:
                SetColorByRenderBit(ptr,0xffffff);
                break;
            }
        }
        for(int n=0; n<nSensors; n++) {
            if(++hhh[n]>=uiWidth) hhh[n]=0;
        }
    }
    SetColorByRenderBit(0,0xffffff);
}

void textrender()
{
    int y[4];
    y[0]=position.y;
    y[1]=position.y;
    y[2]=position.y2;
    y[3]=position.y2;
    for(int n=0; n<nTexSensors; n++) {
        int c=TexSensors[n]->getColor(0,0);
        int corner=TexSensors[n]->corner;
        int f=TexSensors[n]->getFont(0,0);
        int yy=GetFontYSIZE(f);
        int p=y[corner];
        y[corner] += corner<2 ? yy : -yy;
        DrawString(TexSensors[n]->getText(0,0),
                   position.x,
                   (corner<2 ? p : p-yy),
                   position.x2,
                   (corner<2 ? p+yy : p),
                   f,
                   (corner==0||corner==2) ? TEXT_ALIGNLEFT : TEXT_ALIGNRIGHT,
                   (char *)c,
                   0);
    }
}

void render()
{
    if (cfgTextRender) textrender();

    if (!cfgRender)
        render_BoBa();
    else {
        render_Sinclair();
    }

    RECT rc;
    DRWOBJ drwobj;
    StoreXYWHtoRECT(&rc, position.x, position.y, img1.w, img1.h);
    SetPropTo_Obj5(&drwobj, &rc, 0, &img1);
    SetColor(&drwobj, 0, 0);
    DrawObject(&drwobj);

    if (!cfgTextRender) textrender();
}
