#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <time.h>

#include "resource.h"

#define mxDirs 10000
#define mxFiles 64000
#define mxFileL 1024*512
#define mxQBuff 102400
#define mxQl1 32
#define mxQl2 64

// FILE_ATTRIBUTE_DIRECTORY extension
#define FADE_USERS 17
#define FADE_HID 18
#define FADE_SYSHID 22
#define FADE_UNKNOWN 48
#define FADE_RECOVERY 8214
#define FADE_DOCSETS 9238
#define FADE_WIN 65552
#define FADE_PROGFILES 65553

int l, lDir, iC=10, qL, qL2, cp1251to866_ar [256],
    fC [mxFiles], rC [mxFiles], rCs [mxFiles];

char cp [256], query [mxQl1],
     files [mxFiles] [_MAX_PATH], dir [mxDirs] [_MAX_PATH];

unsigned long long tl=0;

//bool once=false;

void cp1251to866 ()
{
 int i;

 for (i=0; i<strlen (cp); i++)
 {
  if (256+cp [i]<256)
  {
   if (cp1251to866_ar [256+cp [i]])
    cp [i]=cp1251to866_ar [256+cp [i]];
  }
 }

 printf ("%s", cp);
}

int number (int tn)
{
 char t1 [16], t2 [2];
 memset (t2, 0, 2);

 sprintf (t1, "%d", tn);
 t2 [0]=t1 [strlen (t1)-1];
 tn=atoi (t2);

 if (strlen (t1)>1 && t1 [strlen (t1)-2]=='1' && tn>0 && tn<10)
  return 2;
 else if (tn==1)
  return 0;
 else if (tn>1 && tn<5)
  return 1;
 else
  return 2;
}

bool exists (char fPath [_MAX_PATH])
{
 char tPath [_MAX_PATH];
 WIN32_FIND_DATA FindFileData;
 HANDLE hf;

 sprintf (tPath, "%s", fPath);

 if (strlen (tPath)<2)
  return false;
 else if (strlen (tPath)<4)
 {
  if (tPath [strlen (tPath)-1]=='\\')
   strcat (tPath, "*");
  else
   strcat (tPath, "\\*");
 }
 else if (tPath [strlen (tPath)-1]=='\\')
  tPath [strlen (tPath)-1]='\0';

 hf=FindFirstFile (tPath, &FindFileData);

 if (hf!=INVALID_HANDLE_VALUE)
  return true;
 else
  return false;
}

void load ()
{
 int i;
 char path [_MAX_PATH];
 l=0;
 lDir=1;

 WIN32_FIND_DATA FindFileData;
 HANDLE hf;

 for (i=0; i<lDir && i<mxDirs; i++)
 {
  sprintf (path, "%s%s", dir [i], "*.*");
  hf=FindFirstFile (path, &FindFileData);

  if (hf!=INVALID_HANDLE_VALUE)
  {
   while (true)
   {
    if (FindFileData.dwFileAttributes!=FADE_SYSHID
     && FindFileData.dwFileAttributes!=FADE_RECOVERY
     && FindFileData.dwFileAttributes!=FADE_DOCSETS
     && FindFileData.dwFileAttributes!=FADE_WIN)
    {
     if (FindFileData.dwFileAttributes!=FILE_ATTRIBUTE_DIRECTORY
      && FindFileData.dwFileAttributes!=FADE_USERS
      && FindFileData.dwFileAttributes!=FADE_HID
      && FindFileData.dwFileAttributes!=FADE_UNKNOWN
      && FindFileData.dwFileAttributes!=FADE_PROGFILES)
     {
      sprintf (files [l], "%s%s", dir [i], FindFileData.cFileName);
      // more 4GB
      tl+=(FindFileData.nFileSizeHigh*21474836470/10*2+FindFileData.nFileSizeLow)/1024;//...0/10?, (MAXDWORD+1)
      l++;
     }
     else if (strcmp (FindFileData.cFileName, ".") && strcmp (FindFileData.cFileName, ".."))
     {
      sprintf (dir [lDir], "%s%s\\", dir [i], FindFileData.cFileName);
      lDir++;
     }
    }

    if (FindNextFile(hf, &FindFileData)==0 || lDir>=mxDirs || l>=mxFiles)
     break;
   }
  }
 }

 sprintf (cp, " Всего файлов: %d, директорий: %d", l, lDir);
 cp1251to866 ();
}

int main (int argc, char *argv[])
{
 char AppPath [_MAX_PATH], cfgPath [_MAX_PATH], ask [10];
 int i, ap_l=0, iL, i2, i3, n, n2, c, s, rL=0, mx, rLmx, cL, timeS;
 FILE *file;

 for (i=0; i<256; i++)
  cp1251to866_ar [i]=0;

 cp1251to866_ar [168]=240; cp1251to866_ar [184]=241; cp1251to866_ar [192]=128; cp1251to866_ar [193]=129; cp1251to866_ar [194]=130;
 cp1251to866_ar [195]=131; cp1251to866_ar [196]=132; cp1251to866_ar [197]=133; cp1251to866_ar [198]=134; cp1251to866_ar [199]=135;
 cp1251to866_ar [200]=136; cp1251to866_ar [201]=137; cp1251to866_ar [202]=138; cp1251to866_ar [203]=139; cp1251to866_ar [204]=140;
 cp1251to866_ar [205]=141; cp1251to866_ar [206]=142; cp1251to866_ar [207]=143; cp1251to866_ar [208]=144; cp1251to866_ar [209]=145;
 cp1251to866_ar [210]=146; cp1251to866_ar [211]=147; cp1251to866_ar [212]=148; cp1251to866_ar [213]=149; cp1251to866_ar [214]=150;
 cp1251to866_ar [215]=151; cp1251to866_ar [216]=152; cp1251to866_ar [217]=153; cp1251to866_ar [218]=154; cp1251to866_ar [219]=155;
 cp1251to866_ar [220]=156; cp1251to866_ar [221]=157; cp1251to866_ar [222]=158; cp1251to866_ar [223]=159; cp1251to866_ar [224]=160;
 cp1251to866_ar [225]=161; cp1251to866_ar [226]=162; cp1251to866_ar [227]=163; cp1251to866_ar [228]=164; cp1251to866_ar [229]=165;
 cp1251to866_ar [230]=166; cp1251to866_ar [231]=167; cp1251to866_ar [232]=168; cp1251to866_ar [233]=169; cp1251to866_ar [234]=170;
 cp1251to866_ar [235]=171; cp1251to866_ar [236]=172; cp1251to866_ar [237]=173; cp1251to866_ar [238]=174; cp1251to866_ar [239]=175;
 cp1251to866_ar [240]=224; cp1251to866_ar [241]=225; cp1251to866_ar [242]=226; cp1251to866_ar [243]=227; cp1251to866_ar [244]=228;
 cp1251to866_ar [245]=229; cp1251to866_ar [246]=230; cp1251to866_ar [247]=231; cp1251to866_ar [248]=232; cp1251to866_ar [249]=233;
 cp1251to866_ar [250]=234; cp1251to866_ar [251]=235; cp1251to866_ar [252]=236; cp1251to866_ar [253]=237; cp1251to866_ar [254]=238;
 cp1251to866_ar [255]=239;


 char txt [_MAX_PATH];
 memset (txt, 0, _MAX_PATH);
 GetModuleFileName (NULL, txt, _MAX_PATH);
 for (i=_MAX_PATH-1; i>=0 && ap_l==0; i--)
 {
  if (txt [i]=='\\')
   ap_l=i+1;
 }

 for (i=0; i<ap_l; i++)
  AppPath [i]=txt [i];

 memset (cfgPath, 0, _MAX_PATH);
 memcpy (cfgPath, AppPath, ap_l);
 strcat (cfgPath, "data\\config.txt");

 char qDir [_MAX_PATH], qDir2 [_MAX_PATH], qp [mxQBuff];

 sprintf (cp, "\n");
  strcat (cp, " Утилита для копирования файлов\n");
  strcat (cp, " из каталога со множеством поддиректорий\n");
  strcat (cp, " в один каталог.\n");
 cp1251to866 ();

 file=fopen (cfgPath, "rb");
 if (file!=NULL)
 {
  fgets (qDir2, _MAX_PATH, file);
  fclose (file);
 }

 if (strlen (qDir2)>0 && exists (qDir2))
 {
  sprintf (cp, "\n Введите \"s\", чтобы пропустить вопрос\n и задать путь \"%s\".", qDir2);
  cp1251to866 ();

  while (true)
  {
   sprintf (cp, "\n Директория? ");
   cp1251to866 ();

   scanf ("%s", qp); 
   memset (qDir, 0, _MAX_PATH);
   strncpy (qDir, qp, _MAX_PATH-1);

   if (qDir [1]!=':')// !strcmp (qDir, "s")
   {
    sprintf (qDir, "%s", qDir2);
    break;
   }
   else
   {
    for (i=0; i<strlen (qDir); i++)
     if (qDir [i]=='%')
      qDir [i]=' ';

    if (exists (qDir))
    {
     file=fopen (cfgPath, "wb");
     if (file!=NULL)
     {
      fputs (qDir, file);
      fclose (file);
     }

     break;
    }
    else
    {
     sprintf (cp, " Такой директории нет.");
     cp1251to866 ();
    }
   }
  }
 }
 else
 {
  while (true)
  {
   sprintf (cp, "\n Директория? ");
   cp1251to866 ();

   scanf ("%s", qp);
   memset (qDir, 0, _MAX_PATH);
   strncpy (qDir, qp, _MAX_PATH-1);
   for (i=0; i<strlen (qDir); i++)
    if (qDir [i]=='%')
     qDir [i]=' ';

   if (exists (qDir))
    break;
   else
   {
    sprintf (cp, " Такой директории нет.");
    cp1251to866 ();
   }
  }

  file=fopen (cfgPath, "wb");
  if (file!=NULL)
  {
   fputs (qDir, file);
   fclose (file);
  }
 }

 if (qDir [strlen (qDir)-1]!='\\')
  strcat (qDir, "\\");

 sprintf (dir [0], "%s", qDir);

 rL=0; rLmx=0; qL=strlen (query);

 if (argc>2)
  rLmx=atoi (argv [2]);

 FILE *fOpen;
 char fBody [mxFileL+_MAX_PATH+2];

 char basePath [_MAX_PATH], tPath [_MAX_PATH],
      listPath [_MAX_PATH], copyFile [_MAX_PATH], nameFile [_MAX_PATH];

 sprintf (basePath, "%s", dir [0]);
 memset (listPath, 0, _MAX_PATH);

 memcpy (listPath, basePath, strlen (basePath)-1);
 strcat (listPath, ".list");
  mkdir (listPath);

 timeS=clock ();

 load ();

 for (i=0; i<l; i++)
 {
  fC [i]=0;
  rC [i]=0;
  rCs [i]=0;
 }

 printf ("\n");

 sprintf (cp, " Выполнено: ");
 cp1251to866 ();
 char ps [4];
 memset (ps, 0, 4);
 int pr=0, lp=-1;
 if (!l)
  printf ("100%c", 37);

 char pre [10], pre_s [10];
 int pre_l=0;
 sprintf (pre_s, "%d", l);
 pre_l=strlen (pre_s);
  
 for (i=0; i<l; i++)
 {
  pr=(i+1)*100/l;
  if (pr!=lp)
  {
   for (int ip=0; ip<strlen (ps); ip++)
    printf ("%c", 8);
   printf ("%d%c", pr, 37);
   sprintf (ps, "%d+", pr);
   lp=pr;
  }

  fOpen=fopen (files [i], "rb");
  if (fOpen!=NULL)
  {
   memset (nameFile, 0, _MAX_PATH);
   n=strlen (files [i])-1;
   for (i2=n; i2>0; i2--)
   {
    if (files [i] [i2]=='\\')
    {
     n2=strlen (files [i]);
     for (i3=i2+1; i3<n2; i3++)
      nameFile [i3-i2-1]=files [i] [i3]; 
     break;
    }
   }

   memset (pre, 0, 10);
   memcpy (pre, "0000000000", pre_l);
   sprintf (pre_s, "%d", i+1);
   n=0+(pre_l-strlen (pre_s));
   for (i2=pre_l-1; i2>=n; i2--)
   pre [i2]=pre_s [i2-(pre_l-strlen (pre_s))];
   sprintf (copyFile, "%s\\%s_%s", listPath, pre, nameFile);
   bool r=CopyFile (files [i], copyFile, false);
//   if (r)
//    printf (" %s -> %s_%s\n", nameFile, pre, nameFile);
   fclose (fOpen);
  }
 }

 char timeP [16], timeP1 [16], timeP2 [16];
 int minutes=0;
 float seconds=float (float (clock ()-timeS)/1000);
 char minutesN [3] [16]={"минуту", "минуты", "минут"};

 if (seconds>=60)
 {
  minutes=seconds/60;
  seconds-=minutes*60;
  sprintf (timeP1, "%d", minutes);
  sprintf (timeP2, "%f", seconds);
  for (i=0; i<5; i++)
   timeP2 [strlen (timeP2)-1]='\0';

  sprintf (timeP, "%s %s %s с.", timeP1, minutesN [number (minutes)], timeP2);
 }
 else
 {
  sprintf (timeP2, "%f", seconds);
  for (i=0; i<5; i++)
   timeP2 [strlen (timeP2)-1]='\0';

  sprintf (timeP, "%s с.", timeP2);
 }

 sprintf (cp, "\n Обработка заняла: %s\n", timeP);
 cp1251to866 ();

 printf ("%c", 7);// beep

 printf ("\n");

 sprintf (cp, " Файлы извлечены и помещены в директорию с расширением");
  strcat (cp, " \".list\" рядом с обработанным каталогом.\n");
 cp1251to866 ();
 sprintf (cp, " Нажмите клавишу \"Enter\" для выхода и просмотра файлов...");
 cp1251to866 ();

 scanf ("%c", qp);// query
 scanf ("%c", qp);// query

 char tc [_MAX_PATH+12];
 sprintf (tc, "explorer %s", listPath);
 system (tc);
}