I64 sc_1, sc_2;

#define DROPS_NUM           0x2000

class Drop
{
    I32 x, y;
} drops[DROPS_NUM];

CDC *cur_dc;

U0 DrawFrame(CTask *task, CDC *dc)
{
    I64 w = task->pix_width, h = task->pix_height, cx = w >> 1, cy = h >> 1;

    dc->color = LTRED;
    GrLine(dc, cx - 20, cy - 50, cx, cy - 150);
    GrLine(dc, cx + 20, cy - 50, cx, cy - 150);

    dc->color = LTRED;
    GrLine(dc, cx - 100, cy - 100, cx, cy);
    GrLine(dc, cx + 100, cy - 100, cx, cy);
    if (Bt(kbd.down_bitmap, sc_1))
    {
        dc->color = WHITE;
        GrRect(dc, cx - 2, cy - 2, 5, 5);
    }
    dc->color = BLACK;
    GrPrint(dc, cx + 10, cy, "Press '1'");

    dc->color = LTRED;
    GrRect(dc, cx - 20, cy + 60, 41, 21);

    dc->color = LTRED;
    GrLine(dc, cx - 200, cy, cx, cy + 100);
    GrLine(dc, cx + 200, cy, cx, cy + 100);
    if (Bt(kbd.down_bitmap, sc_2))
    {
        dc->color = WHITE;
        GrRect(dc, cx - 2, cy + 100 - 2, 5, 5);
    }
    dc->color = BLACK;
    GrPrint(dc, cx + 10, cy + 100, "Press '2'");

    dc->color = LTRED;
    GrLine(dc, cx + 400, cy + 100, cx - 250, cy + 200);
}

U0 DrawDrops(CTask *, CDC *dc)
{
    I64 i;

    dc->color = BLUE;
    for (i = 0; i < DROPS_NUM; i++)
        if (drops[i].y >= 0 && GrPeek(dc, drops[i].x, drops[i].y) == WHITE)
            GrPlot(dc, drops[i].x, drops[i].y);
}

U0 UpdateCurBase(CTask *task, CDC *dc)
{
    cur_dc->color = ROP_EQU;
    dc->flags |= DCF_NO_TRANSPARENTS;
    GrBlot(cur_dc, -task->pix_left - task->scroll_x, -task->pix_top - task->scroll_y, dc);
    dc->flags &= ~DCF_NO_TRANSPARENTS;
}

U0 DrawIt(CTask *task, CDC *dc)
{
    DrawFrame(task, dc);
    DrawDrops(task, dc);
    UpdateCurBase(task, dc);
}

U0 AnimateTask(I64)
{
    I64 i, j, cur_drop = 0, c1, c2, x0, y0, x1, y1, w, h;

    while (TRUE)
    {
        w = Fs->parent_task->pix_width;
        h = Fs->parent_task->pix_height;

        for (i = 0; i < 2; i++)
        {
            j = 0;
            do
            {
                if (++cur_drop >= DROPS_NUM)
                    cur_drop = 0;
                if (drops[cur_drop].y < 0)
                    break;
                j++;
            }
            while (j <= DROPS_NUM);

            drops[cur_drop].x = RandU32%w;
            drops[cur_drop].y = 0;
        }

        for (i = 0; i < DROPS_NUM; i++)
        {
            if (drops[i].y >= 0)
            {
                if (drops[i].y >= h - 1)
                    drops[i].y = -I32_MAX;
                else
                {
                    x0 = x1 = drops[i].x;
                    y0 = y1 = drops[i].y;
                    if (GrPeek(cur_dc, x0, y0 + 1) == WHITE)
                        y1++;
                    else
                    {
                        c1 = GrPeek(cur_dc, x0 + 1, y0);
                        c2 = GrPeek(cur_dc, x0 - 1, y0);
                        if (c1 == WHITE && c2 != WHITE)
                            x1++;
                        else if (c2 == WHITE && c1 != WHITE)
                            x1--;
                        else if (c1 == WHITE && c2 == WHITE)
                        {
                            c1 = GrPeek(cur_dc, x0 + 1, y0 + 1);
                            c2 = GrPeek(cur_dc, x0 - 1, y0 + 1);
                            if (c1 == WHITE && c2 != WHITE)
                                x1++;
                            else if (c2 == WHITE && c1 != WHITE)
                                x1--;
                            else if (RandI16 >= 0)
                                x1++;
                            else
                                x1--;
                        }
                        if (GrPeek(cur_dc, x1, y1 + 1) == WHITE)
                            y1++;
                    }
                    if (GrPeek(cur_dc, x0, y0) == BLUE)
                    {
                        cur_dc->color = WHITE;
                        GrPlot(cur_dc, x0, y0);
                    }
                    cur_dc->color = BLUE;
                    GrPlot(cur_dc, x1, y1);
                    drops[i].x = x1;
                    drops[i].y = y1;
                }
            }
        }
        Sleep(10);
    }
}

U0 Init()
{
    I64 i;

    MemSet(drops, 0, sizeof(drops));
    for (i = 0; i < DROPS_NUM;i ++)
        drops[i].y = -I32_MAX;
}

U0 RainDrops()
{
    I64 ch, sc;

    MenuPush(   "File {"
                "  Abort(,CH_SHIFT_ESC);"
                "  Exit(,CH_ESC);"
                "}"
                "Play {"
                "  Restart(,'\n');"
                "  OpenUpper(,'1');"
                "  OpenLower(,'2');"
                "}"
                );
    SettingsPush; //See SettingsPush
    AutoComplete;
    WinBorder;
    WinMax;
    DocCursor;
    DocClear;
    cur_dc = DCNew(GR_WIDTH, GR_HEIGHT);
    sc_1 = Char2ScanCode('1');
    sc_2 = Char2ScanCode('2');
    Init;
    Fs->animate_task = Spawn(&AnimateTask, NULL, "Animate",, Fs);
    Fs->draw_it      = &DrawIt;
    try
    {
        do
            switch (ch = KeyGet(&sc))
            {
                case '\n':
                    Init;
                    break;
            }
        while (ch != CH_ESC && ch != CH_SHIFT_ESC);
    }
    catch
        PutExcept;
    SettingsPop;
    MenuPop;
    DCDel(cur_dc);
}

RainDrops;