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=GetKey(&sc)) {
        case '\n':
          Init;
          break;
      }
    while (ch!=CH_ESC && ch!=CH_SHIFT_ESC);
  } catch
    PutExcept;
  SettingsPop;
  MenuPop;
  DCDel(cur_dc);
}

RainDrops;