#include "stdafx.h"
#define SET_FIRST
#include <afxmt.h>
#include "TranslateW.h"

void CheckStop();

//int SetStopGlobal=0;
struct SThreadBlock
{
 SThreadBlock(){clean();}
 void clean(){InternalHandle=Handle=INVALID_HANDLE_VALUE;State=0;SetStop=0;VRoutine=0;ThreadID=0;FRoutine=NULL;obrabotka=NULL;}
 HANDLE Handle,InternalHandle;//=INVALID_HANDLE_VALUE;
 int State;//=0;//0=initial; 1=started
 int SetStop;//=0;
 DWORD /*WINAPI*/ (*FRoutine)(LPVOID lpThreadParameter);//=NULL;
 int (*obrabotka)();
 int VRoutine;//=0;
 DWORD ThreadID;//=0;
 int PeriodSec;
 int DtFirstWait;
 int SetFirstCall;
 CString Name;
};

CMutex Mutex_StartStopBlock;

#define NThBlockMax 100
SThreadBlock ThBlock[NThBlockMax];  int NThBlock=0;

double vvod(CString text, double MinValue, double MaxValue)
{
double v=0;
 if(InputValue)
  v=InputValue(text, MinValue, MaxValue);
 return v;
}
double vybor(CString text, CString s1,double v1, CString s2,double v2,CString s3,double v3,CString s4,double v4,CString s5,double v5,CString s6,double v6,CString s7,double v7,CString s8,double v8,CString s9,double v9,CString s10,double v10,CString s11,double v11)
{
 double rtn=FSelect(text, s1,v1, s2,v2,s3,v3,s4,v4,s5,v5,s6,v6,s7,v7,s8,v8,s9,v9,s10,v10,s11,v11);
 return rtn;
}

double muljltivybor(CString text, CString s1,double *v1, CString s2,double *v2,CString s3,double *v3,CString s4,double *v4,CString s5,double *v5,CString s6,double *v6,CString s7,double *v7,CString s8,double *v8,CString s9,double *v9,CString s10,double *v10,CString s11,double *v11)
{
 double rtn=FMultiSelect(text, s1,v1, s2,v2,s3,v3,s4,v4,s5,v5,s6,v6,s7,v7,s8,v8,s9,v9,s10,v10,s11,v11);
 return rtn;
}

int SetInjectionQuick(const char *OutputText,int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,INJ_TYPE InjectionType,UNIT_TYPE UnitType)
{
 if(FSetInjectionQuick==NULL)
  return -1;
 int rtn=FSetInjectionQuick(OutputText,InusomatNum,DrugType,DrugName,Value,InjectionType,UnitType);
 return rtn;
}
int SetInjection(const char *OutputText,int SetWait,int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,UNIT_TYPE UnitType,int T
 ,double Value2,UNIT_TYPE UnitType2,int t2
 ,double Value3,UNIT_TYPE UnitType3,int t3
 ,double Value4,UNIT_TYPE UnitType4,int t4
 ,double Value5,UNIT_TYPE UnitType5,int t5)
{
 if(FSetInjection==NULL)
  return -1;
 int rtn=FSetInjection(OutputText,SetWait,InusomatNum,DrugType,DrugName,Value,UnitType,T
 ,Value2,UnitType2,t2
 ,Value3,UnitType3,t3
 ,Value4,UnitType4,t4
 ,Value5,UnitType5,t5);
 return 0;
}
int SetInjectionVelocity(int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,UNIT_TYPE UnitType)
{
 if(FSetInjectionVelocity==NULL)
  return -1;
 int rtn=FSetInjectionVelocity(InusomatNum,DrugType,DrugName,Value,UnitType);
 return 0;
}

DWORD WINAPI /* _cdecl*/ BlockThreadRoutine(LPVOID lpThreadParameter)
{
 SThreadBlock *th=(SThreadBlock*)lpThreadParameter; int rtn=0;
 th->InternalHandle=GetCurrentThread();
 while(th->SetStop==0&&(SetStopGlobal==NULL||*SetStopGlobal==0))
 {
  if(th->SetFirstCall)
  {
   th->SetFirstCall=0;
   for(int i=0;i<th->DtFirstWait;i++)
   {
    Sleep(1000);//th->PeriodSec*1000);
    if(th->SetStop||(SetStopGlobal&&*SetStopGlobal))
     goto le;
   }
  }
  rtn=th->obrabotka();
  if(th->SetStop||(SetStopGlobal&&*SetStopGlobal))
   break;
  for(int i=0;i<th->PeriodSec;i++)
  {
   Sleep(1000);//th->PeriodSec*1000);
   if(th->SetStop||(SetStopGlobal&&*SetStopGlobal))
    goto le;
  }
 }
le:;
 th->clean();
return 0;
}


int ActivateBlock(int (*obrabotka)(),int PeriodTimeSec,const char *SNameBlock,int DtFirstWait)
{//  MargThreadHandle=CreateThread(NULL,0, MargRoutine, &VMargRoutine, 0,&MargThreadID);
 int iThBlock;
 CSingleLock lockI(&Mutex_StartStopBlock);
 if(lockI.Lock(1000))
 {
  if(NThBlock>=NThBlockMax)
   {AfxMessageBox("(20031308) NThBlock>=NThBlockMax");return -1;}
  for(iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].Handle==INVALID_HANDLE_VALUE)
     break;
  if(iThBlock==NThBlock)
   NThBlock++;
  ThBlock[iThBlock].clean();
  ThBlock[iThBlock].State=1;
  ThBlock[iThBlock].SetStop=0;
  ThBlock[iThBlock].obrabotka=obrabotka;
  ThBlock[iThBlock].PeriodSec=PeriodTimeSec;
  ThBlock[iThBlock].DtFirstWait=DtFirstWait;
  ThBlock[iThBlock].Name=SNameBlock;
  ThBlock[iThBlock].SetFirstCall=1;
  lockI.Unlock();
 }
 else 
 {
  AfxMessageBox("(183334)Can't lock ");
  return -1;
 }
 CheckStop();
 ThBlock[iThBlock].InternalHandle=INVALID_HANDLE_VALUE;
 ThBlock[iThBlock].Handle=CreateThread(NULL,0, BlockThreadRoutine, ThBlock+iThBlock/*&VBlockThreadRoutine*/, 0,&ThBlock[iThBlock].ThreadID);
 for(int i=0;i<20;i++)
 {if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE)break;Sleep(100);}
 Sleep(500);
 Output(CString("Активирован блок '")+SNameBlock+"'");
 return 0;
}
int FSleep(int Interval)
{
	int n=FGetRealTime(Interval);
 for(int i=0;i<n*2;i++)
 {
  if(SetStopGlobal&&*SetStopGlobal)
   return 0;
  Sleep(500);
 }
 return 0;
}
int SetInterval(INT_TYPE type,int Interval)
{
// SThreadBlock *th=(SThreadBlock*)lpThreadParameter; //int rtn=0;
// th->InternalHandle=GetCurrentThread();
//int SetNeedHandsValues[7];//CHSS=1,CHDD=2,AD=3,SPO2=4,DIUREZ=5,TEMP=6
if(type==CHSS)SetNeedHandsValues[CHSS]=1;
if(type==CHDD)SetNeedHandsValues[CHDD]=1;
if(type==AD)SetNeedHandsValues[AD]=1;
if(type==SPO2)SetNeedHandsValues[SPO2]=1;
if(type==DIUREZ)SetNeedHandsValues[DIUREZ]=1;
if(type==TEMP)SetNeedHandsValues[TEMP]=1;
float  *v=(type==CHSS?vCHSS_: type==CHDD?vCHDD_: type==AD?vSAD_: type==SPO2?vSpO2_:type==TEMP?vTemp_: NULL);
 if(v==NULL)
  return -1;
 while(*v<0&&(/*th->SetStop==0&&*/(SetStopGlobal==NULL||*SetStopGlobal==0)))
  Sleep(200);
 return 0;
}
int SetDiurez(int Interval)
{
 return 0;
}
int CallDoctor(const char *str,int WaitTime)
{
 if(FDoctorCall)
 {
  DWORD id=GetCurrentThreadId();
  int iThBlock;
  for(iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE && ThBlock[iThBlock].ThreadID==id)
   {CString header; header.Format("Внимание!!! (из блока '%s')",ThBlock[iThBlock].Name);
    CheckStop();
    int rtn=FDoctorCall(WaitTime,str,header);
    CheckStop();
    return rtn;
   }
   {CString header; header.Format("Внимание!!!");
    CheckStop();
    int rtn=FDoctorCall(WaitTime,str,header);
    CheckStop();
    return rtn;
   }
  return -1;
 }
 return -1;
}
int Output(const char *str)
{
 CheckStop();
 if(AddShowStr)
  AddShowStr(str);
 CheckStop();
 return 0;
}
int SleepBeforeOK(const char *str,int WaitTime)
{
 if(FDoctorCall)
 {
  DWORD id=GetCurrentThreadId();
  int iThBlock;
  for(iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE && ThBlock[iThBlock].ThreadID==id)
   {CString header; header.Format("Ожидание врача из блока '%s'!!!",ThBlock[iThBlock].Name);
    CheckStop();
    int rtn=FDoctorCall(WaitTime,str,header);
    CheckStop();
    return rtn;
   }
  return -1;
 }
 return -1;
}

int WaitThreadsEnd() 
{
 HANDLE hdl=GetCurrentThread();
 DWORD id=GetCurrentThreadId();
 int iThBlock,used=1;
 for(used=1;used;Sleep(100))
 {
  for(used=0,iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE && ThBlock[iThBlock].State)
   {used=1;break;}
   //used=1;
//  if(SetStopGlobal&&*SetStopGlobal)
//   break;
 }
 Output("Все блоки завершили работу");
return 0;
}

int TotalStop(void)
{
 if(SetStopGlobal==NULL||*SetStopGlobal==0)
  Output("Завершение работы всех блоков");
 if(SetStopGlobal)
  *SetStopGlobal=1;
return 0;
}
int StopBlock(void)
{
 CSingleLock lockI(&Mutex_StartStopBlock);
 if(lockI.Lock(1000))
 {
  HANDLE hdl=GetCurrentThread();
  DWORD id=GetCurrentThreadId();
  int iThBlock;
  for(iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE && ThBlock[iThBlock].ThreadID==id) //&& ThBlock[iThBlock].InternalHandle==hdl)
   {
     ThBlock[iThBlock].SetStop=1;
     ThBlock[iThBlock].Handle=INVALID_HANDLE_VALUE;
     ThBlock[iThBlock].InternalHandle=INVALID_HANDLE_VALUE;
     Output(CString("Остановлен блок '")+ThBlock[iThBlock].Name+"'");
     lockI.Unlock();
     ExitThread(0);
     return 0;
   }
  AfxMessageBox("(20031351)Can't find thread to stop ");
  lockI.Unlock();
 }else 
  AfxMessageBox("(183335)Can't lock ");
 return 0;
}

//__declspec(dllexport) int SetAddData(int Type, void *ptr,int size)
extern "C" int PASCAL EXPORT SetAddData(int Type, void *ptr,int size)
{
 if(Type==1)
  AddShowStr=(void (*)(const char *str))ptr;
 if(Type==2)
  InputValue=(double (*)(const char *str, double MinValue, double MaxValue))ptr;
 if(Type==3)
  FSelect=(double (*)(const char* text, const char* s1,double v1, const char* s2,double v2,const char* s3,double v3,const char* s4,double v4,const char* s5,double v5,const char* s6,double v6,const char* s7,double v7,const char* s8,double v8,const char* s9,double v9,const char* s10,double v10,const char* s11,double v11))ptr;
 if(Type==4)//int FDoctorCall(int nSeconds,const char *text);
  FDoctorCall=(int (*)(int nSeconds,const char *text,const char *header))ptr;
 if(Type==5)//SetStopGlobal
  SetStopGlobal=(int*)ptr;
 //int *vCHSS_,*vCHDD_,*vSAD_,*vDAD_,*vSpO2_;
 if(Type==6)
  vCHSS_=(float*)ptr;
 if(Type==7)
  vCHDD_=(float*)ptr;
 if(Type==8)
  vSAD_=(float*)ptr;
 if(Type==9)
  vDAD_=(float*)ptr;
 if(Type==10)
  vSpO2_=(float*)ptr;
 if(Type==11)
  vTemp_=(float*)ptr;
 if(Type==12)
  SetNeedHandsValues=(int*)ptr;
 if(Type==13)
  FSetInjectionQuick= (int (*)(const char *OutputText,int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,INJ_TYPE InjectionType,UNIT_TYPE UnitType))ptr;
 if(Type==14)
  FSetInjection=(int (*)(const char *OutputText,int SetWait,int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,UNIT_TYPE UnitType,int T
 ,double Value2,UNIT_TYPE UnitType2,int t2
 ,double Value3,UNIT_TYPE UnitType3,int t3
 ,double Value4,UNIT_TYPE UnitType4,int t4
 ,double Value5,UNIT_TYPE UnitType5,int t5))ptr;
 if(Type==15)
  FSetInjectionVelocity=(int (*)(int InusomatNum,DRUG_TYPE DrugType,const char *DrugName,double Value,UNIT_TYPE UnitType))ptr;
 if(Type==16)
  vAD_=(float*)ptr;
 if(Type==17)
  FSetInjectionStop=(int(*)(int))ptr;
 if(Type==18)
  TimeCountStart=(int(*)(void))ptr;
 if(Type==19)
  TimeCountSec=(int(*)(void))ptr;
 if(Type==20)
  TimeCountMin=(int(*)(void))ptr;
 if(Type==21)
  TimeCountH=(int(*)(void))ptr;
 if(Type==22)
  TimeCountTotalSec=(int(*)(void))ptr;
 if(Type==23)
  FMultiSelect=(double (*)(const char* text, const char* s1,double *v1, const char* s2,double *v2,const char* s3,double *v3,const char* s4,double *v4,const char* s5,double *v5,const char* s6,double *v6,const char* s7,double *v7,const char* s8,double *v8,const char* s9,double *v9,const char* s10,double *v10,const char* s11,double *v11))ptr;
 if(Type==24)
  FGetRealTime=(int (*)(int))ptr;
return 0;
}

void CheckStop()
{
 CSingleLock lockI(&Mutex_StartStopBlock);
 if(lockI.Lock(1000))
 {
  DWORD id=GetCurrentThreadId();
  int iThBlock;
  for(iThBlock=0;iThBlock<NThBlock;iThBlock++)
   if(ThBlock[iThBlock].InternalHandle!=INVALID_HANDLE_VALUE && 
     (ThBlock[iThBlock].ThreadID==id&&((SetStopGlobal&&*SetStopGlobal)||ThBlock[iThBlock].SetStop))
     )
   {
     ThBlock[iThBlock].SetStop=1;
     ThBlock[iThBlock].Handle=INVALID_HANDLE_VALUE;
     ThBlock[iThBlock].InternalHandle=INVALID_HANDLE_VALUE;
     Output(CString("Остановлен блок '")+ThBlock[iThBlock].Name+"'");
     lockI.Unlock();
     ExitThread(0);
     return;
   }
//  AfxMessageBox("(20031351)Can't find thread to stop ");
  lockI.Unlock();
 }else 
  AfxMessageBox("(183336)Can't lock ");
}


int SetInjectionStop(int InusomatNum)
{
 if(FSetInjectionStop==NULL)
  return -1;
 int rtn=FSetInjectionStop(InusomatNum);
return rtn;
}
